linux/drivers/rtc/rtc-pcf8583.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 *  drivers/rtc/rtc-pcf8583.c
   4 *
   5 *  Copyright (C) 2000 Russell King
   6 *  Copyright (C) 2008 Wolfram Sang & Juergen Beisert, Pengutronix
   7 *
   8 *  Driver for PCF8583 RTC & RAM chip
   9 *
  10 *  Converted to the generic RTC susbsystem by G. Liakhovetski (2006)
  11 */
  12#include <linux/module.h>
  13#include <linux/i2c.h>
  14#include <linux/slab.h>
  15#include <linux/rtc.h>
  16#include <linux/init.h>
  17#include <linux/err.h>
  18#include <linux/errno.h>
  19#include <linux/bcd.h>
  20
  21struct rtc_mem {
  22        unsigned int    loc;
  23        unsigned int    nr;
  24        unsigned char   *data;
  25};
  26
  27struct pcf8583 {
  28        struct rtc_device *rtc;
  29        unsigned char ctrl;
  30};
  31
  32#define CTRL_STOP       0x80
  33#define CTRL_HOLD       0x40
  34#define CTRL_32KHZ      0x00
  35#define CTRL_MASK       0x08
  36#define CTRL_ALARMEN    0x04
  37#define CTRL_ALARM      0x02
  38#define CTRL_TIMER      0x01
  39
  40
  41static struct i2c_driver pcf8583_driver;
  42
  43#define get_ctrl(x)    ((struct pcf8583 *)i2c_get_clientdata(x))->ctrl
  44#define set_ctrl(x, v) get_ctrl(x) = v
  45
  46#define CMOS_YEAR       (64 + 128)
  47#define CMOS_CHECKSUM   (63)
  48
  49static int pcf8583_get_datetime(struct i2c_client *client, struct rtc_time *dt)
  50{
  51        unsigned char buf[8], addr[1] = { 1 };
  52        struct i2c_msg msgs[2] = {
  53                {
  54                        .addr = client->addr,
  55                        .flags = 0,
  56                        .len = 1,
  57                        .buf = addr,
  58                }, {
  59                        .addr = client->addr,
  60                        .flags = I2C_M_RD,
  61                        .len = 6,
  62                        .buf = buf,
  63                }
  64        };
  65        int ret;
  66
  67        memset(buf, 0, sizeof(buf));
  68
  69        ret = i2c_transfer(client->adapter, msgs, 2);
  70        if (ret == 2) {
  71                dt->tm_year = buf[4] >> 6;
  72                dt->tm_wday = buf[5] >> 5;
  73
  74                buf[4] &= 0x3f;
  75                buf[5] &= 0x1f;
  76
  77                dt->tm_sec = bcd2bin(buf[1]);
  78                dt->tm_min = bcd2bin(buf[2]);
  79                dt->tm_hour = bcd2bin(buf[3]);
  80                dt->tm_mday = bcd2bin(buf[4]);
  81                dt->tm_mon = bcd2bin(buf[5]) - 1;
  82        }
  83
  84        return ret == 2 ? 0 : -EIO;
  85}
  86
  87static int pcf8583_set_datetime(struct i2c_client *client, struct rtc_time *dt, int datetoo)
  88{
  89        unsigned char buf[8];
  90        int ret, len = 6;
  91
  92        buf[0] = 0;
  93        buf[1] = get_ctrl(client) | 0x80;
  94        buf[2] = 0;
  95        buf[3] = bin2bcd(dt->tm_sec);
  96        buf[4] = bin2bcd(dt->tm_min);
  97        buf[5] = bin2bcd(dt->tm_hour);
  98
  99        if (datetoo) {
 100                len = 8;
 101                buf[6] = bin2bcd(dt->tm_mday) | (dt->tm_year << 6);
 102                buf[7] = bin2bcd(dt->tm_mon + 1)  | (dt->tm_wday << 5);
 103        }
 104
 105        ret = i2c_master_send(client, (char *)buf, len);
 106        if (ret != len)
 107                return -EIO;
 108
 109        buf[1] = get_ctrl(client);
 110        ret = i2c_master_send(client, (char *)buf, 2);
 111
 112        return ret == 2 ? 0 : -EIO;
 113}
 114
 115static int pcf8583_get_ctrl(struct i2c_client *client, unsigned char *ctrl)
 116{
 117        *ctrl = get_ctrl(client);
 118        return 0;
 119}
 120
 121static int pcf8583_set_ctrl(struct i2c_client *client, unsigned char *ctrl)
 122{
 123        unsigned char buf[2];
 124
 125        buf[0] = 0;
 126        buf[1] = *ctrl;
 127        set_ctrl(client, *ctrl);
 128
 129        return i2c_master_send(client, (char *)buf, 2);
 130}
 131
 132static int pcf8583_read_mem(struct i2c_client *client, struct rtc_mem *mem)
 133{
 134        unsigned char addr[1];
 135        struct i2c_msg msgs[2] = {
 136                {
 137                        .addr = client->addr,
 138                        .flags = 0,
 139                        .len = 1,
 140                        .buf = addr,
 141                }, {
 142                        .addr = client->addr,
 143                        .flags = I2C_M_RD,
 144                        .len = mem->nr,
 145                        .buf = mem->data,
 146                }
 147        };
 148
 149        if (mem->loc < 8)
 150                return -EINVAL;
 151
 152        addr[0] = mem->loc;
 153
 154        return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO;
 155}
 156
 157static int pcf8583_write_mem(struct i2c_client *client, struct rtc_mem *mem)
 158{
 159        unsigned char buf[9];
 160        int ret;
 161
 162        if (mem->loc < 8 || mem->nr > 8)
 163                return -EINVAL;
 164
 165        buf[0] = mem->loc;
 166        memcpy(buf + 1, mem->data, mem->nr);
 167
 168        ret = i2c_master_send(client, buf, mem->nr + 1);
 169        return ret == mem->nr + 1 ? 0 : -EIO;
 170}
 171
 172static int pcf8583_rtc_read_time(struct device *dev, struct rtc_time *tm)
 173{
 174        struct i2c_client *client = to_i2c_client(dev);
 175        unsigned char ctrl, year[2];
 176        struct rtc_mem mem = {
 177                .loc = CMOS_YEAR,
 178                .nr = sizeof(year),
 179                .data = year
 180        };
 181        int real_year, year_offset, err;
 182
 183        /*
 184         * Ensure that the RTC is running.
 185         */
 186        pcf8583_get_ctrl(client, &ctrl);
 187        if (ctrl & (CTRL_STOP | CTRL_HOLD)) {
 188                unsigned char new_ctrl = ctrl & ~(CTRL_STOP | CTRL_HOLD);
 189
 190                dev_warn(dev, "resetting control %02x -> %02x\n",
 191                        ctrl, new_ctrl);
 192
 193                err = pcf8583_set_ctrl(client, &new_ctrl);
 194                if (err < 0)
 195                        return err;
 196        }
 197
 198        if (pcf8583_get_datetime(client, tm) ||
 199            pcf8583_read_mem(client, &mem))
 200                return -EIO;
 201
 202        real_year = year[0];
 203
 204        /*
 205         * The RTC year holds the LSB two bits of the current
 206         * year, which should reflect the LSB two bits of the
 207         * CMOS copy of the year.  Any difference indicates
 208         * that we have to correct the CMOS version.
 209         */
 210        year_offset = tm->tm_year - (real_year & 3);
 211        if (year_offset < 0)
 212                /*
 213                 * RTC year wrapped.  Adjust it appropriately.
 214                 */
 215                year_offset += 4;
 216
 217        tm->tm_year = (real_year + year_offset + year[1] * 100) - 1900;
 218
 219        return 0;
 220}
 221
 222static int pcf8583_rtc_set_time(struct device *dev, struct rtc_time *tm)
 223{
 224        struct i2c_client *client = to_i2c_client(dev);
 225        unsigned char year[2], chk;
 226        struct rtc_mem cmos_year  = {
 227                .loc = CMOS_YEAR,
 228                .nr = sizeof(year),
 229                .data = year
 230        };
 231        struct rtc_mem cmos_check = {
 232                .loc = CMOS_CHECKSUM,
 233                .nr = 1,
 234                .data = &chk
 235        };
 236        unsigned int proper_year = tm->tm_year + 1900;
 237        int ret;
 238
 239        /*
 240         * The RTC's own 2-bit year must reflect the least
 241         * significant two bits of the CMOS year.
 242         */
 243
 244        ret = pcf8583_set_datetime(client, tm, 1);
 245        if (ret)
 246                return ret;
 247
 248        ret = pcf8583_read_mem(client, &cmos_check);
 249        if (ret)
 250                return ret;
 251
 252        ret = pcf8583_read_mem(client, &cmos_year);
 253        if (ret)
 254                return ret;
 255
 256        chk -= year[1] + year[0];
 257
 258        year[1] = proper_year / 100;
 259        year[0] = proper_year % 100;
 260
 261        chk += year[1] + year[0];
 262
 263        ret = pcf8583_write_mem(client, &cmos_year);
 264
 265        if (ret)
 266                return ret;
 267
 268        ret = pcf8583_write_mem(client, &cmos_check);
 269
 270        return ret;
 271}
 272
 273static const struct rtc_class_ops pcf8583_rtc_ops = {
 274        .read_time      = pcf8583_rtc_read_time,
 275        .set_time       = pcf8583_rtc_set_time,
 276};
 277
 278static int pcf8583_probe(struct i2c_client *client,
 279                                const struct i2c_device_id *id)
 280{
 281        struct pcf8583 *pcf8583;
 282
 283        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
 284                return -ENODEV;
 285
 286        pcf8583 = devm_kzalloc(&client->dev, sizeof(struct pcf8583),
 287                                GFP_KERNEL);
 288        if (!pcf8583)
 289                return -ENOMEM;
 290
 291        i2c_set_clientdata(client, pcf8583);
 292
 293        pcf8583->rtc = devm_rtc_device_register(&client->dev,
 294                                pcf8583_driver.driver.name,
 295                                &pcf8583_rtc_ops, THIS_MODULE);
 296
 297        return PTR_ERR_OR_ZERO(pcf8583->rtc);
 298}
 299
 300static const struct i2c_device_id pcf8583_id[] = {
 301        { "pcf8583", 0 },
 302        { }
 303};
 304MODULE_DEVICE_TABLE(i2c, pcf8583_id);
 305
 306static struct i2c_driver pcf8583_driver = {
 307        .driver = {
 308                .name   = "pcf8583",
 309        },
 310        .probe          = pcf8583_probe,
 311        .id_table       = pcf8583_id,
 312};
 313
 314module_i2c_driver(pcf8583_driver);
 315
 316MODULE_AUTHOR("Russell King");
 317MODULE_DESCRIPTION("PCF8583 I2C RTC driver");
 318MODULE_LICENSE("GPL");
 319