linux/drivers/rtc/rtc-isl12057.c
<<
>>
Prefs
   1/*
   2 * rtc-isl12057 - Driver for Intersil ISL12057 I2C Real Time Clock
   3 *
   4 * Copyright (C) 2013, Arnaud EBALARD <arno@natisbad.org>
   5 *
   6 * This work is largely based on Intersil ISL1208 driver developed by
   7 * Hebert Valerio Riedel <hvr@gnu.org>.
   8 *
   9 * Detailed datasheet on which this development is based is available here:
  10 *
  11 *  http://natisbad.org/NAS2/refs/ISL12057.pdf
  12 *
  13 * This program is free software; you can redistribute it and/or modify
  14 * it under the terms of the GNU General Public License as published by
  15 * the Free Software Foundation; either version 2 of the License, or
  16 * (at your option) any later version.
  17 *
  18 * This program is distributed in the hope that it will be useful,
  19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21 * GNU General Public License for more details.
  22 */
  23
  24#include <linux/module.h>
  25#include <linux/mutex.h>
  26#include <linux/rtc.h>
  27#include <linux/i2c.h>
  28#include <linux/bcd.h>
  29#include <linux/of.h>
  30#include <linux/of_device.h>
  31#include <linux/regmap.h>
  32
  33#define DRV_NAME "rtc-isl12057"
  34
  35/* RTC section */
  36#define ISL12057_REG_RTC_SC     0x00    /* Seconds */
  37#define ISL12057_REG_RTC_MN     0x01    /* Minutes */
  38#define ISL12057_REG_RTC_HR     0x02    /* Hours */
  39#define ISL12057_REG_RTC_HR_PM  BIT(5)  /* AM/PM bit in 12h format */
  40#define ISL12057_REG_RTC_HR_MIL BIT(6)  /* 24h/12h format */
  41#define ISL12057_REG_RTC_DW     0x03    /* Day of the Week */
  42#define ISL12057_REG_RTC_DT     0x04    /* Date */
  43#define ISL12057_REG_RTC_MO     0x05    /* Month */
  44#define ISL12057_REG_RTC_MO_CEN BIT(7)  /* Century bit */
  45#define ISL12057_REG_RTC_YR     0x06    /* Year */
  46#define ISL12057_RTC_SEC_LEN    7
  47
  48/* Alarm 1 section */
  49#define ISL12057_REG_A1_SC      0x07    /* Alarm 1 Seconds */
  50#define ISL12057_REG_A1_MN      0x08    /* Alarm 1 Minutes */
  51#define ISL12057_REG_A1_HR      0x09    /* Alarm 1 Hours */
  52#define ISL12057_REG_A1_HR_PM   BIT(5)  /* AM/PM bit in 12h format */
  53#define ISL12057_REG_A1_HR_MIL  BIT(6)  /* 24h/12h format */
  54#define ISL12057_REG_A1_DWDT    0x0A    /* Alarm 1 Date / Day of the week */
  55#define ISL12057_REG_A1_DWDT_B  BIT(6)  /* DW / DT selection bit */
  56#define ISL12057_A1_SEC_LEN     4
  57
  58/* Alarm 2 section */
  59#define ISL12057_REG_A2_MN      0x0B    /* Alarm 2 Minutes */
  60#define ISL12057_REG_A2_HR      0x0C    /* Alarm 2 Hours */
  61#define ISL12057_REG_A2_DWDT    0x0D    /* Alarm 2 Date / Day of the week */
  62#define ISL12057_A2_SEC_LEN     3
  63
  64/* Control/Status registers */
  65#define ISL12057_REG_INT        0x0E
  66#define ISL12057_REG_INT_A1IE   BIT(0)  /* Alarm 1 interrupt enable bit */
  67#define ISL12057_REG_INT_A2IE   BIT(1)  /* Alarm 2 interrupt enable bit */
  68#define ISL12057_REG_INT_INTCN  BIT(2)  /* Interrupt control enable bit */
  69#define ISL12057_REG_INT_RS1    BIT(3)  /* Freq out control bit 1 */
  70#define ISL12057_REG_INT_RS2    BIT(4)  /* Freq out control bit 2 */
  71#define ISL12057_REG_INT_EOSC   BIT(7)  /* Oscillator enable bit */
  72
  73#define ISL12057_REG_SR         0x0F
  74#define ISL12057_REG_SR_A1F     BIT(0)  /* Alarm 1 interrupt bit */
  75#define ISL12057_REG_SR_A2F     BIT(1)  /* Alarm 2 interrupt bit */
  76#define ISL12057_REG_SR_OSF     BIT(7)  /* Oscillator failure bit */
  77
  78/* Register memory map length */
  79#define ISL12057_MEM_MAP_LEN    0x10
  80
  81struct isl12057_rtc_data {
  82        struct regmap *regmap;
  83        struct mutex lock;
  84};
  85
  86static void isl12057_rtc_regs_to_tm(struct rtc_time *tm, u8 *regs)
  87{
  88        tm->tm_sec = bcd2bin(regs[ISL12057_REG_RTC_SC]);
  89        tm->tm_min = bcd2bin(regs[ISL12057_REG_RTC_MN]);
  90
  91        if (regs[ISL12057_REG_RTC_HR] & ISL12057_REG_RTC_HR_MIL) { /* AM/PM */
  92                tm->tm_hour = bcd2bin(regs[ISL12057_REG_RTC_HR] & 0x1f);
  93                if (regs[ISL12057_REG_RTC_HR] & ISL12057_REG_RTC_HR_PM)
  94                        tm->tm_hour += 12;
  95        } else {                                            /* 24 hour mode */
  96                tm->tm_hour = bcd2bin(regs[ISL12057_REG_RTC_HR] & 0x3f);
  97        }
  98
  99        tm->tm_mday = bcd2bin(regs[ISL12057_REG_RTC_DT]);
 100        tm->tm_wday = bcd2bin(regs[ISL12057_REG_RTC_DW]) - 1; /* starts at 1 */
 101        tm->tm_mon  = bcd2bin(regs[ISL12057_REG_RTC_MO] & 0x1f) - 1; /* ditto */
 102        tm->tm_year = bcd2bin(regs[ISL12057_REG_RTC_YR]) + 100;
 103
 104        /* Check if years register has overflown from 99 to 00 */
 105        if (regs[ISL12057_REG_RTC_MO] & ISL12057_REG_RTC_MO_CEN)
 106                tm->tm_year += 100;
 107}
 108
 109static int isl12057_rtc_tm_to_regs(u8 *regs, struct rtc_time *tm)
 110{
 111        u8 century_bit;
 112
 113        /*
 114         * The clock has an 8 bit wide bcd-coded register for the year.
 115         * It also has a century bit encoded in MO flag which provides
 116         * information about overflow of year register from 99 to 00.
 117         * tm_year is an offset from 1900 and we are interested in the
 118         * 2000-2199 range, so any value less than 100 or larger than
 119         * 299 is invalid.
 120         */
 121        if (tm->tm_year < 100 || tm->tm_year > 299)
 122                return -EINVAL;
 123
 124        century_bit = (tm->tm_year > 199) ? ISL12057_REG_RTC_MO_CEN : 0;
 125
 126        regs[ISL12057_REG_RTC_SC] = bin2bcd(tm->tm_sec);
 127        regs[ISL12057_REG_RTC_MN] = bin2bcd(tm->tm_min);
 128        regs[ISL12057_REG_RTC_HR] = bin2bcd(tm->tm_hour); /* 24-hour format */
 129        regs[ISL12057_REG_RTC_DT] = bin2bcd(tm->tm_mday);
 130        regs[ISL12057_REG_RTC_MO] = bin2bcd(tm->tm_mon + 1) | century_bit;
 131        regs[ISL12057_REG_RTC_YR] = bin2bcd(tm->tm_year % 100);
 132        regs[ISL12057_REG_RTC_DW] = bin2bcd(tm->tm_wday + 1);
 133
 134        return 0;
 135}
 136
 137/*
 138 * Try and match register bits w/ fixed null values to see whether we
 139 * are dealing with an ISL12057. Note: this function is called early
 140 * during init and hence does need mutex protection.
 141 */
 142static int isl12057_i2c_validate_chip(struct regmap *regmap)
 143{
 144        u8 regs[ISL12057_MEM_MAP_LEN];
 145        static const u8 mask[ISL12057_MEM_MAP_LEN] = { 0x80, 0x80, 0x80, 0xf8,
 146                                                       0xc0, 0x60, 0x00, 0x00,
 147                                                       0x00, 0x00, 0x00, 0x00,
 148                                                       0x00, 0x00, 0x60, 0x7c };
 149        int ret, i;
 150
 151        ret = regmap_bulk_read(regmap, 0, regs, ISL12057_MEM_MAP_LEN);
 152        if (ret)
 153                return ret;
 154
 155        for (i = 0; i < ISL12057_MEM_MAP_LEN; ++i) {
 156                if (regs[i] & mask[i])  /* check if bits are cleared */
 157                        return -ENODEV;
 158        }
 159
 160        return 0;
 161}
 162
 163static int isl12057_rtc_read_time(struct device *dev, struct rtc_time *tm)
 164{
 165        struct isl12057_rtc_data *data = dev_get_drvdata(dev);
 166        u8 regs[ISL12057_RTC_SEC_LEN];
 167        unsigned int sr;
 168        int ret;
 169
 170        mutex_lock(&data->lock);
 171        ret = regmap_read(data->regmap, ISL12057_REG_SR, &sr);
 172        if (ret) {
 173                dev_err(dev, "%s: unable to read oscillator status flag (%d)\n",
 174                        __func__, ret);
 175                goto out;
 176        } else {
 177                if (sr & ISL12057_REG_SR_OSF) {
 178                        ret = -ENODATA;
 179                        goto out;
 180                }
 181        }
 182
 183        ret = regmap_bulk_read(data->regmap, ISL12057_REG_RTC_SC, regs,
 184                               ISL12057_RTC_SEC_LEN);
 185        if (ret)
 186                dev_err(dev, "%s: unable to read RTC time section (%d)\n",
 187                        __func__, ret);
 188
 189out:
 190        mutex_unlock(&data->lock);
 191
 192        if (ret)
 193                return ret;
 194
 195        isl12057_rtc_regs_to_tm(tm, regs);
 196
 197        return rtc_valid_tm(tm);
 198}
 199
 200static int isl12057_rtc_set_time(struct device *dev, struct rtc_time *tm)
 201{
 202        struct isl12057_rtc_data *data = dev_get_drvdata(dev);
 203        u8 regs[ISL12057_RTC_SEC_LEN];
 204        int ret;
 205
 206        ret = isl12057_rtc_tm_to_regs(regs, tm);
 207        if (ret)
 208                return ret;
 209
 210        mutex_lock(&data->lock);
 211        ret = regmap_bulk_write(data->regmap, ISL12057_REG_RTC_SC, regs,
 212                                ISL12057_RTC_SEC_LEN);
 213        if (ret) {
 214                dev_err(dev, "%s: unable to write RTC time section (%d)\n",
 215                        __func__, ret);
 216                goto out;
 217        }
 218
 219        /*
 220         * Now that RTC time has been updated, let's clear oscillator
 221         * failure flag, if needed.
 222         */
 223        ret = regmap_update_bits(data->regmap, ISL12057_REG_SR,
 224                                 ISL12057_REG_SR_OSF, 0);
 225        if (ret < 0)
 226                dev_err(dev, "%s: unable to clear osc. failure bit (%d)\n",
 227                        __func__, ret);
 228
 229out:
 230        mutex_unlock(&data->lock);
 231
 232        return ret;
 233}
 234
 235/*
 236 * Check current RTC status and enable/disable what needs to be. Return 0 if
 237 * everything went ok and a negative value upon error. Note: this function
 238 * is called early during init and hence does need mutex protection.
 239 */
 240static int isl12057_check_rtc_status(struct device *dev, struct regmap *regmap)
 241{
 242        int ret;
 243
 244        /* Enable oscillator if not already running */
 245        ret = regmap_update_bits(regmap, ISL12057_REG_INT,
 246                                 ISL12057_REG_INT_EOSC, 0);
 247        if (ret < 0) {
 248                dev_err(dev, "%s: unable to enable oscillator (%d)\n",
 249                        __func__, ret);
 250                return ret;
 251        }
 252
 253        /* Clear alarm bit if needed */
 254        ret = regmap_update_bits(regmap, ISL12057_REG_SR,
 255                                 ISL12057_REG_SR_A1F, 0);
 256        if (ret < 0) {
 257                dev_err(dev, "%s: unable to clear alarm bit (%d)\n",
 258                        __func__, ret);
 259                return ret;
 260        }
 261
 262        return 0;
 263}
 264
 265static const struct rtc_class_ops rtc_ops = {
 266        .read_time = isl12057_rtc_read_time,
 267        .set_time = isl12057_rtc_set_time,
 268};
 269
 270static struct regmap_config isl12057_rtc_regmap_config = {
 271        .reg_bits = 8,
 272        .val_bits = 8,
 273};
 274
 275static int isl12057_probe(struct i2c_client *client,
 276                          const struct i2c_device_id *id)
 277{
 278        struct device *dev = &client->dev;
 279        struct isl12057_rtc_data *data;
 280        struct rtc_device *rtc;
 281        struct regmap *regmap;
 282        int ret;
 283
 284        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
 285                                     I2C_FUNC_SMBUS_BYTE_DATA |
 286                                     I2C_FUNC_SMBUS_I2C_BLOCK))
 287                return -ENODEV;
 288
 289        regmap = devm_regmap_init_i2c(client, &isl12057_rtc_regmap_config);
 290        if (IS_ERR(regmap)) {
 291                ret = PTR_ERR(regmap);
 292                dev_err(dev, "%s: regmap allocation failed (%d)\n",
 293                        __func__, ret);
 294                return ret;
 295        }
 296
 297        ret = isl12057_i2c_validate_chip(regmap);
 298        if (ret)
 299                return ret;
 300
 301        ret = isl12057_check_rtc_status(dev, regmap);
 302        if (ret)
 303                return ret;
 304
 305        data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
 306        if (!data)
 307                return -ENOMEM;
 308
 309        mutex_init(&data->lock);
 310        data->regmap = regmap;
 311        dev_set_drvdata(dev, data);
 312
 313        rtc = devm_rtc_device_register(dev, DRV_NAME, &rtc_ops, THIS_MODULE);
 314        return PTR_ERR_OR_ZERO(rtc);
 315}
 316
 317#ifdef CONFIG_OF
 318static const struct of_device_id isl12057_dt_match[] = {
 319        { .compatible = "isl,isl12057" },
 320        { },
 321};
 322#endif
 323
 324static const struct i2c_device_id isl12057_id[] = {
 325        { "isl12057", 0 },
 326        { }
 327};
 328MODULE_DEVICE_TABLE(i2c, isl12057_id);
 329
 330static struct i2c_driver isl12057_driver = {
 331        .driver = {
 332                .name = DRV_NAME,
 333                .owner = THIS_MODULE,
 334                .of_match_table = of_match_ptr(isl12057_dt_match),
 335        },
 336        .probe    = isl12057_probe,
 337        .id_table = isl12057_id,
 338};
 339module_i2c_driver(isl12057_driver);
 340
 341MODULE_AUTHOR("Arnaud EBALARD <arno@natisbad.org>");
 342MODULE_DESCRIPTION("Intersil ISL12057 RTC driver");
 343MODULE_LICENSE("GPL");
 344
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.