linux/drivers/rtc/rtc-isl12026.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * An I2C driver for the Intersil ISL 12026
   4 *
   5 * Copyright (c) 2018 Cavium, Inc.
   6 */
   7#include <linux/bcd.h>
   8#include <linux/delay.h>
   9#include <linux/i2c.h>
  10#include <linux/module.h>
  11#include <linux/mutex.h>
  12#include <linux/nvmem-provider.h>
  13#include <linux/of.h>
  14#include <linux/of_device.h>
  15#include <linux/rtc.h>
  16#include <linux/slab.h>
  17
  18/* register offsets */
  19#define ISL12026_REG_PWR        0x14
  20# define ISL12026_REG_PWR_BSW   BIT(6)
  21# define ISL12026_REG_PWR_SBIB  BIT(7)
  22#define ISL12026_REG_SC         0x30
  23#define ISL12026_REG_HR         0x32
  24# define ISL12026_REG_HR_MIL    BIT(7)  /* military or 24 hour time */
  25#define ISL12026_REG_SR         0x3f
  26# define ISL12026_REG_SR_RTCF   BIT(0)
  27# define ISL12026_REG_SR_WEL    BIT(1)
  28# define ISL12026_REG_SR_RWEL   BIT(2)
  29# define ISL12026_REG_SR_MBZ    BIT(3)
  30# define ISL12026_REG_SR_OSCF   BIT(4)
  31
  32/* The EEPROM array responds at i2c address 0x57 */
  33#define ISL12026_EEPROM_ADDR    0x57
  34
  35#define ISL12026_PAGESIZE 16
  36#define ISL12026_NVMEM_WRITE_TIME 20
  37
  38struct isl12026 {
  39        struct rtc_device *rtc;
  40        struct i2c_client *nvm_client;
  41};
  42
  43static int isl12026_read_reg(struct i2c_client *client, int reg)
  44{
  45        u8 addr[] = {0, reg};
  46        u8 val;
  47        int ret;
  48
  49        struct i2c_msg msgs[] = {
  50                {
  51                        .addr   = client->addr,
  52                        .flags  = 0,
  53                        .len    = sizeof(addr),
  54                        .buf    = addr
  55                }, {
  56                        .addr   = client->addr,
  57                        .flags  = I2C_M_RD,
  58                        .len    = 1,
  59                        .buf    = &val
  60                }
  61        };
  62
  63        ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
  64        if (ret != ARRAY_SIZE(msgs)) {
  65                dev_err(&client->dev, "read reg error, ret=%d\n", ret);
  66                ret = ret < 0 ? ret : -EIO;
  67        } else {
  68                ret = val;
  69        }
  70
  71        return ret;
  72}
  73
  74static int isl12026_arm_write(struct i2c_client *client)
  75{
  76        int ret;
  77        u8 op[3];
  78        struct i2c_msg msg = {
  79                .addr   = client->addr,
  80                .flags  = 0,
  81                .len    = 1,
  82                .buf    = op
  83        };
  84
  85        /* Set SR.WEL */
  86        op[0] = 0;
  87        op[1] = ISL12026_REG_SR;
  88        op[2] = ISL12026_REG_SR_WEL;
  89        msg.len = 3;
  90        ret = i2c_transfer(client->adapter, &msg, 1);
  91        if (ret != 1) {
  92                dev_err(&client->dev, "write error SR.WEL, ret=%d\n", ret);
  93                ret = ret < 0 ? ret : -EIO;
  94                goto out;
  95        }
  96
  97        /* Set SR.WEL and SR.RWEL */
  98        op[2] = ISL12026_REG_SR_WEL | ISL12026_REG_SR_RWEL;
  99        msg.len = 3;
 100        ret = i2c_transfer(client->adapter, &msg, 1);
 101        if (ret != 1) {
 102                dev_err(&client->dev,
 103                        "write error SR.WEL|SR.RWEL, ret=%d\n", ret);
 104                ret = ret < 0 ? ret : -EIO;
 105                goto out;
 106        } else {
 107                ret = 0;
 108        }
 109out:
 110        return ret;
 111}
 112
 113static int isl12026_disarm_write(struct i2c_client *client)
 114{
 115        int ret;
 116        u8 op[3] = {0, ISL12026_REG_SR, 0};
 117        struct i2c_msg msg = {
 118                .addr   = client->addr,
 119                .flags  = 0,
 120                .len    = sizeof(op),
 121                .buf    = op
 122        };
 123
 124        ret = i2c_transfer(client->adapter, &msg, 1);
 125        if (ret != 1) {
 126                dev_err(&client->dev,
 127                        "write error SR, ret=%d\n", ret);
 128                ret = ret < 0 ? ret : -EIO;
 129        } else {
 130                ret = 0;
 131        }
 132
 133        return ret;
 134}
 135
 136static int isl12026_write_reg(struct i2c_client *client, int reg, u8 val)
 137{
 138        int ret;
 139        u8 op[3] = {0, reg, val};
 140        struct i2c_msg msg = {
 141                .addr   = client->addr,
 142                .flags  = 0,
 143                .len    = sizeof(op),
 144                .buf    = op
 145        };
 146
 147        ret = isl12026_arm_write(client);
 148        if (ret)
 149                return ret;
 150
 151        ret = i2c_transfer(client->adapter, &msg, 1);
 152        if (ret != 1) {
 153                dev_err(&client->dev, "write error CCR, ret=%d\n", ret);
 154                ret = ret < 0 ? ret : -EIO;
 155                goto out;
 156        }
 157
 158        msleep(ISL12026_NVMEM_WRITE_TIME);
 159
 160        ret = isl12026_disarm_write(client);
 161out:
 162        return ret;
 163}
 164
 165static int isl12026_rtc_set_time(struct device *dev, struct rtc_time *tm)
 166{
 167        struct i2c_client *client = to_i2c_client(dev);
 168        int ret;
 169        u8 op[10];
 170        struct i2c_msg msg = {
 171                .addr   = client->addr,
 172                .flags  = 0,
 173                .len    = sizeof(op),
 174                .buf    = op
 175        };
 176
 177        ret = isl12026_arm_write(client);
 178        if (ret)
 179                return ret;
 180
 181        /* Set the CCR registers */
 182        op[0] = 0;
 183        op[1] = ISL12026_REG_SC;
 184        op[2] = bin2bcd(tm->tm_sec); /* SC */
 185        op[3] = bin2bcd(tm->tm_min); /* MN */
 186        op[4] = bin2bcd(tm->tm_hour) | ISL12026_REG_HR_MIL; /* HR */
 187        op[5] = bin2bcd(tm->tm_mday); /* DT */
 188        op[6] = bin2bcd(tm->tm_mon + 1); /* MO */
 189        op[7] = bin2bcd(tm->tm_year % 100); /* YR */
 190        op[8] = bin2bcd(tm->tm_wday & 7); /* DW */
 191        op[9] = bin2bcd(tm->tm_year >= 100 ? 20 : 19); /* Y2K */
 192        ret = i2c_transfer(client->adapter, &msg, 1);
 193        if (ret != 1) {
 194                dev_err(&client->dev, "write error CCR, ret=%d\n", ret);
 195                ret = ret < 0 ? ret : -EIO;
 196                goto out;
 197        }
 198
 199        ret = isl12026_disarm_write(client);
 200out:
 201        return ret;
 202}
 203
 204static int isl12026_rtc_read_time(struct device *dev, struct rtc_time *tm)
 205{
 206        struct i2c_client *client = to_i2c_client(dev);
 207        u8 ccr[8];
 208        u8 addr[2];
 209        u8 sr;
 210        int ret;
 211        struct i2c_msg msgs[] = {
 212                {
 213                        .addr   = client->addr,
 214                        .flags  = 0,
 215                        .len    = sizeof(addr),
 216                        .buf    = addr
 217                }, {
 218                        .addr   = client->addr,
 219                        .flags  = I2C_M_RD,
 220                }
 221        };
 222
 223        /* First, read SR */
 224        addr[0] = 0;
 225        addr[1] = ISL12026_REG_SR;
 226        msgs[1].len = 1;
 227        msgs[1].buf = &sr;
 228
 229        ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
 230        if (ret != ARRAY_SIZE(msgs)) {
 231                dev_err(&client->dev, "read error, ret=%d\n", ret);
 232                ret = ret < 0 ? ret : -EIO;
 233                goto out;
 234        }
 235
 236        if (sr & ISL12026_REG_SR_RTCF)
 237                dev_warn(&client->dev, "Real-Time Clock Failure on read\n");
 238        if (sr & ISL12026_REG_SR_OSCF)
 239                dev_warn(&client->dev, "Oscillator Failure on read\n");
 240
 241        /* Second, CCR regs */
 242        addr[0] = 0;
 243        addr[1] = ISL12026_REG_SC;
 244        msgs[1].len = sizeof(ccr);
 245        msgs[1].buf = ccr;
 246
 247        ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
 248        if (ret != ARRAY_SIZE(msgs)) {
 249                dev_err(&client->dev, "read error, ret=%d\n", ret);
 250                ret = ret < 0 ? ret : -EIO;
 251                goto out;
 252        }
 253
 254        tm->tm_sec = bcd2bin(ccr[0] & 0x7F);
 255        tm->tm_min = bcd2bin(ccr[1] & 0x7F);
 256        if (ccr[2] & ISL12026_REG_HR_MIL)
 257                tm->tm_hour = bcd2bin(ccr[2] & 0x3F);
 258        else
 259                tm->tm_hour = bcd2bin(ccr[2] & 0x1F) +
 260                        ((ccr[2] & 0x20) ? 12 : 0);
 261        tm->tm_mday = bcd2bin(ccr[3] & 0x3F);
 262        tm->tm_mon = bcd2bin(ccr[4] & 0x1F) - 1;
 263        tm->tm_year = bcd2bin(ccr[5]);
 264        if (bcd2bin(ccr[7]) == 20)
 265                tm->tm_year += 100;
 266        tm->tm_wday = ccr[6] & 0x07;
 267
 268        ret = 0;
 269out:
 270        return ret;
 271}
 272
 273static const struct rtc_class_ops isl12026_rtc_ops = {
 274        .read_time      = isl12026_rtc_read_time,
 275        .set_time       = isl12026_rtc_set_time,
 276};
 277
 278static int isl12026_nvm_read(void *p, unsigned int offset,
 279                             void *val, size_t bytes)
 280{
 281        struct isl12026 *priv = p;
 282        int ret;
 283        u8 addr[2];
 284        struct i2c_msg msgs[] = {
 285                {
 286                        .addr   = priv->nvm_client->addr,
 287                        .flags  = 0,
 288                        .len    = sizeof(addr),
 289                        .buf    = addr
 290                }, {
 291                        .addr   = priv->nvm_client->addr,
 292                        .flags  = I2C_M_RD,
 293                        .buf    = val
 294                }
 295        };
 296
 297        /*
 298         * offset and bytes checked and limited by nvmem core, so
 299         * proceed without further checks.
 300         */
 301        ret = mutex_lock_interruptible(&priv->rtc->ops_lock);
 302        if (ret)
 303                return ret;
 304
 305        /* 2 bytes of address, most significant first */
 306        addr[0] = offset >> 8;
 307        addr[1] = offset;
 308        msgs[1].len = bytes;
 309        ret = i2c_transfer(priv->nvm_client->adapter, msgs, ARRAY_SIZE(msgs));
 310
 311        mutex_unlock(&priv->rtc->ops_lock);
 312
 313        if (ret != ARRAY_SIZE(msgs)) {
 314                dev_err(&priv->nvm_client->dev,
 315                        "nvmem read error, ret=%d\n", ret);
 316                return ret < 0 ? ret : -EIO;
 317        }
 318
 319        return 0;
 320}
 321
 322static int isl12026_nvm_write(void *p, unsigned int offset,
 323                              void *val, size_t bytes)
 324{
 325        struct isl12026 *priv = p;
 326        int ret;
 327        u8 *v = val;
 328        size_t chunk_size, num_written;
 329        u8 payload[ISL12026_PAGESIZE + 2]; /* page + 2 address bytes */
 330        struct i2c_msg msgs[] = {
 331                {
 332                        .addr   = priv->nvm_client->addr,
 333                        .flags  = 0,
 334                        .buf    = payload
 335                }
 336        };
 337
 338        /*
 339         * offset and bytes checked and limited by nvmem core, so
 340         * proceed without further checks.
 341         */
 342        ret = mutex_lock_interruptible(&priv->rtc->ops_lock);
 343        if (ret)
 344                return ret;
 345
 346        num_written = 0;
 347        while (bytes) {
 348                chunk_size = round_down(offset, ISL12026_PAGESIZE) +
 349                        ISL12026_PAGESIZE - offset;
 350                chunk_size = min(bytes, chunk_size);
 351                /*
 352                 * 2 bytes of address, most significant first, followed
 353                 * by page data bytes
 354                 */
 355                memcpy(payload + 2, v + num_written, chunk_size);
 356                payload[0] = offset >> 8;
 357                payload[1] = offset;
 358                msgs[0].len = chunk_size + 2;
 359                ret = i2c_transfer(priv->nvm_client->adapter,
 360                                   msgs, ARRAY_SIZE(msgs));
 361                if (ret != ARRAY_SIZE(msgs)) {
 362                        dev_err(&priv->nvm_client->dev,
 363                                "nvmem write error, ret=%d\n", ret);
 364                        ret = ret < 0 ? ret : -EIO;
 365                        break;
 366                }
 367                ret = 0;
 368                bytes -= chunk_size;
 369                offset += chunk_size;
 370                num_written += chunk_size;
 371                msleep(ISL12026_NVMEM_WRITE_TIME);
 372        }
 373
 374        mutex_unlock(&priv->rtc->ops_lock);
 375
 376        return ret;
 377}
 378
 379static void isl12026_force_power_modes(struct i2c_client *client)
 380{
 381        int ret;
 382        int pwr, requested_pwr;
 383        u32 bsw_val, sbib_val;
 384        bool set_bsw, set_sbib;
 385
 386        /*
 387         * If we can read the of_property, set the specified value.
 388         * If there is an error reading the of_property (likely
 389         * because it does not exist), keep the current value.
 390         */
 391        ret = of_property_read_u32(client->dev.of_node,
 392                                   "isil,pwr-bsw", &bsw_val);
 393        set_bsw = (ret == 0);
 394
 395        ret = of_property_read_u32(client->dev.of_node,
 396                                   "isil,pwr-sbib", &sbib_val);
 397        set_sbib = (ret == 0);
 398
 399        /* Check if PWR.BSW and/or PWR.SBIB need specified values */
 400        if (!set_bsw && !set_sbib)
 401                return;
 402
 403        pwr = isl12026_read_reg(client, ISL12026_REG_PWR);
 404        if (pwr < 0) {
 405                dev_warn(&client->dev, "Error: Failed to read PWR %d\n", pwr);
 406                return;
 407        }
 408
 409        requested_pwr = pwr;
 410
 411        if (set_bsw) {
 412                if (bsw_val)
 413                        requested_pwr |= ISL12026_REG_PWR_BSW;
 414                else
 415                        requested_pwr &= ~ISL12026_REG_PWR_BSW;
 416        } /* else keep current BSW */
 417
 418        if (set_sbib) {
 419                if (sbib_val)
 420                        requested_pwr |= ISL12026_REG_PWR_SBIB;
 421                else
 422                        requested_pwr &= ~ISL12026_REG_PWR_SBIB;
 423        } /* else keep current SBIB */
 424
 425        if (pwr >= 0 && pwr != requested_pwr) {
 426                dev_dbg(&client->dev, "PWR: %02x\n", pwr);
 427                dev_dbg(&client->dev, "Updating PWR to: %02x\n", requested_pwr);
 428                isl12026_write_reg(client, ISL12026_REG_PWR, requested_pwr);
 429        }
 430}
 431
 432static int isl12026_probe_new(struct i2c_client *client)
 433{
 434        struct isl12026 *priv;
 435        int ret;
 436        struct nvmem_config nvm_cfg = {
 437                .name = "isl12026-",
 438                .base_dev = &client->dev,
 439                .stride = 1,
 440                .word_size = 1,
 441                .size = 512,
 442                .reg_read = isl12026_nvm_read,
 443                .reg_write = isl12026_nvm_write,
 444        };
 445
 446        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
 447                return -ENODEV;
 448
 449        priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
 450        if (!priv)
 451                return -ENOMEM;
 452
 453        i2c_set_clientdata(client, priv);
 454
 455        isl12026_force_power_modes(client);
 456
 457        priv->nvm_client = i2c_new_dummy_device(client->adapter, ISL12026_EEPROM_ADDR);
 458        if (IS_ERR(priv->nvm_client))
 459                return PTR_ERR(priv->nvm_client);
 460
 461        priv->rtc = devm_rtc_allocate_device(&client->dev);
 462        ret = PTR_ERR_OR_ZERO(priv->rtc);
 463        if (ret)
 464                return ret;
 465
 466        priv->rtc->ops = &isl12026_rtc_ops;
 467        nvm_cfg.priv = priv;
 468        ret = devm_rtc_nvmem_register(priv->rtc, &nvm_cfg);
 469        if (ret)
 470                return ret;
 471
 472        return devm_rtc_register_device(priv->rtc);
 473}
 474
 475static int isl12026_remove(struct i2c_client *client)
 476{
 477        struct isl12026 *priv = i2c_get_clientdata(client);
 478
 479        i2c_unregister_device(priv->nvm_client);
 480        return 0;
 481}
 482
 483static const struct of_device_id isl12026_dt_match[] = {
 484        { .compatible = "isil,isl12026" },
 485        { }
 486};
 487MODULE_DEVICE_TABLE(of, isl12026_dt_match);
 488
 489static struct i2c_driver isl12026_driver = {
 490        .driver         = {
 491                .name   = "rtc-isl12026",
 492                .of_match_table = isl12026_dt_match,
 493        },
 494        .probe_new      = isl12026_probe_new,
 495        .remove         = isl12026_remove,
 496};
 497
 498module_i2c_driver(isl12026_driver);
 499
 500MODULE_DESCRIPTION("ISL 12026 RTC driver");
 501MODULE_LICENSE("GPL");
 502