linux/drivers/rtc/rtc-rv3029c2.c
<<
>>
Prefs
   1/*
   2 * Micro Crystal RV-3029C2 rtc class driver
   3 *
   4 * Author: Gregory Hermant <gregory.hermant@calao-systems.com>
   5 *
   6 * based on previously existing rtc class drivers
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License version 2 as
  10 * published by the Free Software Foundation.
  11 *
  12 * NOTE: Currently this driver only supports the bare minimum for read
  13 * and write the RTC and alarms. The extra features provided by this chip
  14 * (trickle charger, eeprom, T° compensation) are unavailable.
  15 */
  16
  17#include <linux/module.h>
  18#include <linux/i2c.h>
  19#include <linux/bcd.h>
  20#include <linux/rtc.h>
  21
  22/* Register map */
  23/* control section */
  24#define RV3029C2_ONOFF_CTRL             0x00
  25#define RV3029C2_IRQ_CTRL               0x01
  26#define RV3029C2_IRQ_CTRL_AIE           (1 << 0)
  27#define RV3029C2_IRQ_FLAGS              0x02
  28#define RV3029C2_IRQ_FLAGS_AF           (1 << 0)
  29#define RV3029C2_STATUS                 0x03
  30#define RV3029C2_STATUS_VLOW1           (1 << 2)
  31#define RV3029C2_STATUS_VLOW2           (1 << 3)
  32#define RV3029C2_STATUS_SR              (1 << 4)
  33#define RV3029C2_STATUS_PON             (1 << 5)
  34#define RV3029C2_STATUS_EEBUSY          (1 << 7)
  35#define RV3029C2_RST_CTRL               0x04
  36#define RV3029C2_CONTROL_SECTION_LEN    0x05
  37
  38/* watch section */
  39#define RV3029C2_W_SEC                  0x08
  40#define RV3029C2_W_MINUTES              0x09
  41#define RV3029C2_W_HOURS                0x0A
  42#define RV3029C2_REG_HR_12_24           (1<<6)  /* 24h/12h mode */
  43#define RV3029C2_REG_HR_PM              (1<<5)  /* PM/AM bit in 12h mode */
  44#define RV3029C2_W_DATE                 0x0B
  45#define RV3029C2_W_DAYS                 0x0C
  46#define RV3029C2_W_MONTHS               0x0D
  47#define RV3029C2_W_YEARS                0x0E
  48#define RV3029C2_WATCH_SECTION_LEN      0x07
  49
  50/* alarm section */
  51#define RV3029C2_A_SC                   0x10
  52#define RV3029C2_A_MN                   0x11
  53#define RV3029C2_A_HR                   0x12
  54#define RV3029C2_A_DT                   0x13
  55#define RV3029C2_A_DW                   0x14
  56#define RV3029C2_A_MO                   0x15
  57#define RV3029C2_A_YR                   0x16
  58#define RV3029C2_ALARM_SECTION_LEN      0x07
  59
  60/* timer section */
  61#define RV3029C2_TIMER_LOW              0x18
  62#define RV3029C2_TIMER_HIGH             0x19
  63
  64/* temperature section */
  65#define RV3029C2_TEMP_PAGE              0x20
  66
  67/* eeprom data section */
  68#define RV3029C2_E2P_EEDATA1            0x28
  69#define RV3029C2_E2P_EEDATA2            0x29
  70
  71/* eeprom control section */
  72#define RV3029C2_CONTROL_E2P_EECTRL     0x30
  73#define RV3029C2_TRICKLE_1K             (1<<0)  /*  1K resistance */
  74#define RV3029C2_TRICKLE_5K             (1<<1)  /*  5K resistance */
  75#define RV3029C2_TRICKLE_20K            (1<<2)  /* 20K resistance */
  76#define RV3029C2_TRICKLE_80K            (1<<3)  /* 80K resistance */
  77#define RV3029C2_CONTROL_E2P_XTALOFFSET 0x31
  78#define RV3029C2_CONTROL_E2P_QCOEF      0x32
  79#define RV3029C2_CONTROL_E2P_TURNOVER   0x33
  80
  81/* user ram section */
  82#define RV3029C2_USR1_RAM_PAGE          0x38
  83#define RV3029C2_USR1_SECTION_LEN       0x04
  84#define RV3029C2_USR2_RAM_PAGE          0x3C
  85#define RV3029C2_USR2_SECTION_LEN       0x04
  86
  87static int
  88rv3029c2_i2c_read_regs(struct i2c_client *client, u8 reg, u8 *buf,
  89        unsigned len)
  90{
  91        int ret;
  92
  93        if ((reg > RV3029C2_USR1_RAM_PAGE + 7) ||
  94                (reg + len > RV3029C2_USR1_RAM_PAGE + 8))
  95                return -EINVAL;
  96
  97        ret = i2c_smbus_read_i2c_block_data(client, reg, len, buf);
  98        if (ret < 0)
  99                return ret;
 100        if (ret < len)
 101                return -EIO;
 102        return 0;
 103}
 104
 105static int
 106rv3029c2_i2c_write_regs(struct i2c_client *client, u8 reg, u8 const buf[],
 107                        unsigned len)
 108{
 109        if ((reg > RV3029C2_USR1_RAM_PAGE + 7) ||
 110                (reg + len > RV3029C2_USR1_RAM_PAGE + 8))
 111                return -EINVAL;
 112
 113        return i2c_smbus_write_i2c_block_data(client, reg, len, buf);
 114}
 115
 116static int
 117rv3029c2_i2c_get_sr(struct i2c_client *client, u8 *buf)
 118{
 119        int ret = rv3029c2_i2c_read_regs(client, RV3029C2_STATUS, buf, 1);
 120
 121        if (ret < 0)
 122                return -EIO;
 123        dev_dbg(&client->dev, "status = 0x%.2x (%d)\n", buf[0], buf[0]);
 124        return 0;
 125}
 126
 127static int
 128rv3029c2_i2c_set_sr(struct i2c_client *client, u8 val)
 129{
 130        u8 buf[1];
 131        int sr;
 132
 133        buf[0] = val;
 134        sr = rv3029c2_i2c_write_regs(client, RV3029C2_STATUS, buf, 1);
 135        dev_dbg(&client->dev, "status = 0x%.2x (%d)\n", buf[0], buf[0]);
 136        if (sr < 0)
 137                return -EIO;
 138        return 0;
 139}
 140
 141static int
 142rv3029c2_i2c_read_time(struct i2c_client *client, struct rtc_time *tm)
 143{
 144        u8 buf[1];
 145        int ret;
 146        u8 regs[RV3029C2_WATCH_SECTION_LEN] = { 0, };
 147
 148        ret = rv3029c2_i2c_get_sr(client, buf);
 149        if (ret < 0) {
 150                dev_err(&client->dev, "%s: reading SR failed\n", __func__);
 151                return -EIO;
 152        }
 153
 154        ret = rv3029c2_i2c_read_regs(client, RV3029C2_W_SEC , regs,
 155                                        RV3029C2_WATCH_SECTION_LEN);
 156        if (ret < 0) {
 157                dev_err(&client->dev, "%s: reading RTC section failed\n",
 158                        __func__);
 159                return ret;
 160        }
 161
 162        tm->tm_sec = bcd2bin(regs[RV3029C2_W_SEC-RV3029C2_W_SEC]);
 163        tm->tm_min = bcd2bin(regs[RV3029C2_W_MINUTES-RV3029C2_W_SEC]);
 164
 165        /* HR field has a more complex interpretation */
 166        {
 167                const u8 _hr = regs[RV3029C2_W_HOURS-RV3029C2_W_SEC];
 168                if (_hr & RV3029C2_REG_HR_12_24) {
 169                        /* 12h format */
 170                        tm->tm_hour = bcd2bin(_hr & 0x1f);
 171                        if (_hr & RV3029C2_REG_HR_PM)   /* PM flag set */
 172                                tm->tm_hour += 12;
 173                } else /* 24h format */
 174                        tm->tm_hour = bcd2bin(_hr & 0x3f);
 175        }
 176
 177        tm->tm_mday = bcd2bin(regs[RV3029C2_W_DATE-RV3029C2_W_SEC]);
 178        tm->tm_mon = bcd2bin(regs[RV3029C2_W_MONTHS-RV3029C2_W_SEC]) - 1;
 179        tm->tm_year = bcd2bin(regs[RV3029C2_W_YEARS-RV3029C2_W_SEC]) + 100;
 180        tm->tm_wday = bcd2bin(regs[RV3029C2_W_DAYS-RV3029C2_W_SEC]) - 1;
 181
 182        return 0;
 183}
 184
 185static int rv3029c2_rtc_read_time(struct device *dev, struct rtc_time *tm)
 186{
 187        return rv3029c2_i2c_read_time(to_i2c_client(dev), tm);
 188}
 189
 190static int
 191rv3029c2_i2c_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alarm)
 192{
 193        struct rtc_time *const tm = &alarm->time;
 194        int ret;
 195        u8 regs[8];
 196
 197        ret = rv3029c2_i2c_get_sr(client, regs);
 198        if (ret < 0) {
 199                dev_err(&client->dev, "%s: reading SR failed\n", __func__);
 200                return -EIO;
 201        }
 202
 203        ret = rv3029c2_i2c_read_regs(client, RV3029C2_A_SC, regs,
 204                                        RV3029C2_ALARM_SECTION_LEN);
 205
 206        if (ret < 0) {
 207                dev_err(&client->dev, "%s: reading alarm section failed\n",
 208                        __func__);
 209                return ret;
 210        }
 211
 212        tm->tm_sec = bcd2bin(regs[RV3029C2_A_SC-RV3029C2_A_SC] & 0x7f);
 213        tm->tm_min = bcd2bin(regs[RV3029C2_A_MN-RV3029C2_A_SC] & 0x7f);
 214        tm->tm_hour = bcd2bin(regs[RV3029C2_A_HR-RV3029C2_A_SC] & 0x3f);
 215        tm->tm_mday = bcd2bin(regs[RV3029C2_A_DT-RV3029C2_A_SC] & 0x3f);
 216        tm->tm_mon = bcd2bin(regs[RV3029C2_A_MO-RV3029C2_A_SC] & 0x1f) - 1;
 217        tm->tm_year = bcd2bin(regs[RV3029C2_A_YR-RV3029C2_A_SC] & 0x7f) + 100;
 218        tm->tm_wday = bcd2bin(regs[RV3029C2_A_DW-RV3029C2_A_SC] & 0x07) - 1;
 219
 220        return 0;
 221}
 222
 223static int
 224rv3029c2_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 225{
 226        return rv3029c2_i2c_read_alarm(to_i2c_client(dev), alarm);
 227}
 228
 229static int rv3029c2_rtc_i2c_alarm_set_irq(struct i2c_client *client,
 230                                        int enable)
 231{
 232        int ret;
 233        u8 buf[1];
 234
 235        /* enable AIE irq */
 236        ret = rv3029c2_i2c_read_regs(client, RV3029C2_IRQ_CTRL, buf, 1);
 237        if (ret < 0) {
 238                dev_err(&client->dev, "can't read INT reg\n");
 239                return ret;
 240        }
 241        if (enable)
 242                buf[0] |= RV3029C2_IRQ_CTRL_AIE;
 243        else
 244                buf[0] &= ~RV3029C2_IRQ_CTRL_AIE;
 245
 246        ret = rv3029c2_i2c_write_regs(client, RV3029C2_IRQ_CTRL, buf, 1);
 247        if (ret < 0) {
 248                dev_err(&client->dev, "can't set INT reg\n");
 249                return ret;
 250        }
 251
 252        return 0;
 253}
 254
 255static int rv3029c2_rtc_i2c_set_alarm(struct i2c_client *client,
 256                                        struct rtc_wkalrm *alarm)
 257{
 258        struct rtc_time *const tm = &alarm->time;
 259        int ret;
 260        u8 regs[8];
 261
 262        /*
 263         * The clock has an 8 bit wide bcd-coded register (they never learn)
 264         * for the year. tm_year is an offset from 1900 and we are interested
 265         * in the 2000-2099 range, so any value less than 100 is invalid.
 266        */
 267        if (tm->tm_year < 100)
 268                return -EINVAL;
 269
 270        ret = rv3029c2_i2c_get_sr(client, regs);
 271        if (ret < 0) {
 272                dev_err(&client->dev, "%s: reading SR failed\n", __func__);
 273                return -EIO;
 274        }
 275        regs[RV3029C2_A_SC-RV3029C2_A_SC] = bin2bcd(tm->tm_sec & 0x7f);
 276        regs[RV3029C2_A_MN-RV3029C2_A_SC] = bin2bcd(tm->tm_min & 0x7f);
 277        regs[RV3029C2_A_HR-RV3029C2_A_SC] = bin2bcd(tm->tm_hour & 0x3f);
 278        regs[RV3029C2_A_DT-RV3029C2_A_SC] = bin2bcd(tm->tm_mday & 0x3f);
 279        regs[RV3029C2_A_MO-RV3029C2_A_SC] = bin2bcd((tm->tm_mon & 0x1f) - 1);
 280        regs[RV3029C2_A_DW-RV3029C2_A_SC] = bin2bcd((tm->tm_wday & 7) - 1);
 281        regs[RV3029C2_A_YR-RV3029C2_A_SC] = bin2bcd((tm->tm_year & 0x7f) - 100);
 282
 283        ret = rv3029c2_i2c_write_regs(client, RV3029C2_A_SC, regs,
 284                                        RV3029C2_ALARM_SECTION_LEN);
 285        if (ret < 0)
 286                return ret;
 287
 288        if (alarm->enabled) {
 289                u8 buf[1];
 290
 291                /* clear AF flag */
 292                ret = rv3029c2_i2c_read_regs(client, RV3029C2_IRQ_FLAGS,
 293                                                buf, 1);
 294                if (ret < 0) {
 295                        dev_err(&client->dev, "can't read alarm flag\n");
 296                        return ret;
 297                }
 298                buf[0] &= ~RV3029C2_IRQ_FLAGS_AF;
 299                ret = rv3029c2_i2c_write_regs(client, RV3029C2_IRQ_FLAGS,
 300                                                buf, 1);
 301                if (ret < 0) {
 302                        dev_err(&client->dev, "can't set alarm flag\n");
 303                        return ret;
 304                }
 305                /* enable AIE irq */
 306                ret = rv3029c2_rtc_i2c_alarm_set_irq(client, 1);
 307                if (ret)
 308                        return ret;
 309
 310                dev_dbg(&client->dev, "alarm IRQ armed\n");
 311        } else {
 312                /* disable AIE irq */
 313                ret = rv3029c2_rtc_i2c_alarm_set_irq(client, 1);
 314                if (ret)
 315                        return ret;
 316
 317                dev_dbg(&client->dev, "alarm IRQ disabled\n");
 318        }
 319
 320        return 0;
 321}
 322
 323static int rv3029c2_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 324{
 325        return rv3029c2_rtc_i2c_set_alarm(to_i2c_client(dev), alarm);
 326}
 327
 328static int
 329rv3029c2_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm)
 330{
 331        u8 regs[8];
 332        int ret;
 333
 334        /*
 335         * The clock has an 8 bit wide bcd-coded register (they never learn)
 336         * for the year. tm_year is an offset from 1900 and we are interested
 337         * in the 2000-2099 range, so any value less than 100 is invalid.
 338        */
 339        if (tm->tm_year < 100)
 340                return -EINVAL;
 341
 342        regs[RV3029C2_W_SEC-RV3029C2_W_SEC] = bin2bcd(tm->tm_sec);
 343        regs[RV3029C2_W_MINUTES-RV3029C2_W_SEC] = bin2bcd(tm->tm_min);
 344        regs[RV3029C2_W_HOURS-RV3029C2_W_SEC] = bin2bcd(tm->tm_hour);
 345        regs[RV3029C2_W_DATE-RV3029C2_W_SEC] = bin2bcd(tm->tm_mday);
 346        regs[RV3029C2_W_MONTHS-RV3029C2_W_SEC] = bin2bcd(tm->tm_mon+1);
 347        regs[RV3029C2_W_DAYS-RV3029C2_W_SEC] = bin2bcd((tm->tm_wday & 7)+1);
 348        regs[RV3029C2_W_YEARS-RV3029C2_W_SEC] = bin2bcd(tm->tm_year - 100);
 349
 350        ret = rv3029c2_i2c_write_regs(client, RV3029C2_W_SEC, regs,
 351                                        RV3029C2_WATCH_SECTION_LEN);
 352        if (ret < 0)
 353                return ret;
 354
 355        ret = rv3029c2_i2c_get_sr(client, regs);
 356        if (ret < 0) {
 357                dev_err(&client->dev, "%s: reading SR failed\n", __func__);
 358                return ret;
 359        }
 360        /* clear PON bit */
 361        ret = rv3029c2_i2c_set_sr(client, (regs[0] & ~RV3029C2_STATUS_PON));
 362        if (ret < 0) {
 363                dev_err(&client->dev, "%s: reading SR failed\n", __func__);
 364                return ret;
 365        }
 366
 367        return 0;
 368}
 369
 370static int rv3029c2_rtc_set_time(struct device *dev, struct rtc_time *tm)
 371{
 372        return rv3029c2_i2c_set_time(to_i2c_client(dev), tm);
 373}
 374
 375static const struct rtc_class_ops rv3029c2_rtc_ops = {
 376        .read_time      = rv3029c2_rtc_read_time,
 377        .set_time       = rv3029c2_rtc_set_time,
 378        .read_alarm     = rv3029c2_rtc_read_alarm,
 379        .set_alarm      = rv3029c2_rtc_set_alarm,
 380};
 381
 382static struct i2c_device_id rv3029c2_id[] = {
 383        { "rv3029c2", 0 },
 384        { }
 385};
 386MODULE_DEVICE_TABLE(i2c, rv3029c2_id);
 387
 388static int rv3029c2_probe(struct i2c_client *client,
 389                          const struct i2c_device_id *id)
 390{
 391        struct rtc_device *rtc;
 392        int rc = 0;
 393        u8 buf[1];
 394
 395        if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_EMUL))
 396                return -ENODEV;
 397
 398        rtc = rtc_device_register(client->name,
 399                                &client->dev, &rv3029c2_rtc_ops,
 400                                THIS_MODULE);
 401
 402        if (IS_ERR(rtc))
 403                return PTR_ERR(rtc);
 404
 405        i2c_set_clientdata(client, rtc);
 406
 407        rc = rv3029c2_i2c_get_sr(client, buf);
 408        if (rc < 0) {
 409                dev_err(&client->dev, "reading status failed\n");
 410                goto exit_unregister;
 411        }
 412
 413        return 0;
 414
 415exit_unregister:
 416        rtc_device_unregister(rtc);
 417
 418        return rc;
 419}
 420
 421static int rv3029c2_remove(struct i2c_client *client)
 422{
 423        struct rtc_device *rtc = i2c_get_clientdata(client);
 424
 425        rtc_device_unregister(rtc);
 426
 427        return 0;
 428}
 429
 430static struct i2c_driver rv3029c2_driver = {
 431        .driver = {
 432                .name = "rtc-rv3029c2",
 433        },
 434        .probe = rv3029c2_probe,
 435        .remove = rv3029c2_remove,
 436        .id_table = rv3029c2_id,
 437};
 438
 439module_i2c_driver(rv3029c2_driver);
 440
 441MODULE_AUTHOR("Gregory Hermant <gregory.hermant@calao-systems.com>");
 442MODULE_DESCRIPTION("Micro Crystal RV3029C2 RTC driver");
 443MODULE_LICENSE("GPL");
 444
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.