Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * An I2C driver for the Intersil ISL 12022
0004  *
0005  * Author: Roman Fietze <roman.fietze@telemotive.de>
0006  *
0007  * Based on the Philips PCF8563 RTC
0008  * by Alessandro Zummo <a.zummo@towertech.it>.
0009  */
0010 
0011 #include <linux/i2c.h>
0012 #include <linux/bcd.h>
0013 #include <linux/rtc.h>
0014 #include <linux/slab.h>
0015 #include <linux/module.h>
0016 #include <linux/err.h>
0017 #include <linux/of.h>
0018 #include <linux/of_device.h>
0019 
0020 /* ISL register offsets */
0021 #define ISL12022_REG_SC     0x00
0022 #define ISL12022_REG_MN     0x01
0023 #define ISL12022_REG_HR     0x02
0024 #define ISL12022_REG_DT     0x03
0025 #define ISL12022_REG_MO     0x04
0026 #define ISL12022_REG_YR     0x05
0027 #define ISL12022_REG_DW     0x06
0028 
0029 #define ISL12022_REG_SR     0x07
0030 #define ISL12022_REG_INT    0x08
0031 
0032 /* ISL register bits */
0033 #define ISL12022_HR_MIL     (1 << 7)    /* military or 24 hour time */
0034 
0035 #define ISL12022_SR_LBAT85  (1 << 2)
0036 #define ISL12022_SR_LBAT75  (1 << 1)
0037 
0038 #define ISL12022_INT_WRTC   (1 << 6)
0039 
0040 
0041 static struct i2c_driver isl12022_driver;
0042 
0043 struct isl12022 {
0044     struct rtc_device *rtc;
0045 
0046     bool write_enabled; /* true if write enable is set */
0047 };
0048 
0049 
0050 static int isl12022_read_regs(struct i2c_client *client, uint8_t reg,
0051                   uint8_t *data, size_t n)
0052 {
0053     struct i2c_msg msgs[] = {
0054         {
0055             .addr   = client->addr,
0056             .flags  = 0,
0057             .len    = 1,
0058             .buf    = data
0059         },      /* setup read ptr */
0060         {
0061             .addr   = client->addr,
0062             .flags  = I2C_M_RD,
0063             .len    = n,
0064             .buf    = data
0065         }
0066     };
0067 
0068     int ret;
0069 
0070     data[0] = reg;
0071     ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
0072     if (ret != ARRAY_SIZE(msgs)) {
0073         dev_err(&client->dev, "%s: read error, ret=%d\n",
0074             __func__, ret);
0075         return -EIO;
0076     }
0077 
0078     return 0;
0079 }
0080 
0081 
0082 static int isl12022_write_reg(struct i2c_client *client,
0083                   uint8_t reg, uint8_t val)
0084 {
0085     uint8_t data[2] = { reg, val };
0086     int err;
0087 
0088     err = i2c_master_send(client, data, sizeof(data));
0089     if (err != sizeof(data)) {
0090         dev_err(&client->dev,
0091             "%s: err=%d addr=%02x, data=%02x\n",
0092             __func__, err, data[0], data[1]);
0093         return -EIO;
0094     }
0095 
0096     return 0;
0097 }
0098 
0099 
0100 /*
0101  * In the routines that deal directly with the isl12022 hardware, we use
0102  * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
0103  */
0104 static int isl12022_rtc_read_time(struct device *dev, struct rtc_time *tm)
0105 {
0106     struct i2c_client *client = to_i2c_client(dev);
0107     uint8_t buf[ISL12022_REG_INT + 1];
0108     int ret;
0109 
0110     ret = isl12022_read_regs(client, ISL12022_REG_SC, buf, sizeof(buf));
0111     if (ret)
0112         return ret;
0113 
0114     if (buf[ISL12022_REG_SR] & (ISL12022_SR_LBAT85 | ISL12022_SR_LBAT75)) {
0115         dev_warn(&client->dev,
0116              "voltage dropped below %u%%, "
0117              "date and time is not reliable.\n",
0118              buf[ISL12022_REG_SR] & ISL12022_SR_LBAT85 ? 85 : 75);
0119     }
0120 
0121     dev_dbg(&client->dev,
0122         "%s: raw data is sec=%02x, min=%02x, hr=%02x, "
0123         "mday=%02x, mon=%02x, year=%02x, wday=%02x, "
0124         "sr=%02x, int=%02x",
0125         __func__,
0126         buf[ISL12022_REG_SC],
0127         buf[ISL12022_REG_MN],
0128         buf[ISL12022_REG_HR],
0129         buf[ISL12022_REG_DT],
0130         buf[ISL12022_REG_MO],
0131         buf[ISL12022_REG_YR],
0132         buf[ISL12022_REG_DW],
0133         buf[ISL12022_REG_SR],
0134         buf[ISL12022_REG_INT]);
0135 
0136     tm->tm_sec = bcd2bin(buf[ISL12022_REG_SC] & 0x7F);
0137     tm->tm_min = bcd2bin(buf[ISL12022_REG_MN] & 0x7F);
0138     tm->tm_hour = bcd2bin(buf[ISL12022_REG_HR] & 0x3F);
0139     tm->tm_mday = bcd2bin(buf[ISL12022_REG_DT] & 0x3F);
0140     tm->tm_wday = buf[ISL12022_REG_DW] & 0x07;
0141     tm->tm_mon = bcd2bin(buf[ISL12022_REG_MO] & 0x1F) - 1;
0142     tm->tm_year = bcd2bin(buf[ISL12022_REG_YR]) + 100;
0143 
0144     dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
0145         "mday=%d, mon=%d, year=%d, wday=%d\n",
0146         __func__,
0147         tm->tm_sec, tm->tm_min, tm->tm_hour,
0148         tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
0149 
0150     return 0;
0151 }
0152 
0153 static int isl12022_rtc_set_time(struct device *dev, struct rtc_time *tm)
0154 {
0155     struct i2c_client *client = to_i2c_client(dev);
0156     struct isl12022 *isl12022 = i2c_get_clientdata(client);
0157     size_t i;
0158     int ret;
0159     uint8_t buf[ISL12022_REG_DW + 1];
0160 
0161     dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
0162         "mday=%d, mon=%d, year=%d, wday=%d\n",
0163         __func__,
0164         tm->tm_sec, tm->tm_min, tm->tm_hour,
0165         tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
0166 
0167     if (!isl12022->write_enabled) {
0168 
0169         ret = isl12022_read_regs(client, ISL12022_REG_INT, buf, 1);
0170         if (ret)
0171             return ret;
0172 
0173         /* Check if WRTC (write rtc enable) is set factory default is
0174          * 0 (not set) */
0175         if (!(buf[0] & ISL12022_INT_WRTC)) {
0176             dev_info(&client->dev,
0177                  "init write enable and 24 hour format\n");
0178 
0179             /* Set the write enable bit. */
0180             ret = isl12022_write_reg(client,
0181                          ISL12022_REG_INT,
0182                          buf[0] | ISL12022_INT_WRTC);
0183             if (ret)
0184                 return ret;
0185 
0186             /* Write to any RTC register to start RTC, we use the
0187              * HR register, setting the MIL bit to use the 24 hour
0188              * format. */
0189             ret = isl12022_read_regs(client, ISL12022_REG_HR,
0190                          buf, 1);
0191             if (ret)
0192                 return ret;
0193 
0194             ret = isl12022_write_reg(client,
0195                          ISL12022_REG_HR,
0196                          buf[0] | ISL12022_HR_MIL);
0197             if (ret)
0198                 return ret;
0199         }
0200 
0201         isl12022->write_enabled = true;
0202     }
0203 
0204     /* hours, minutes and seconds */
0205     buf[ISL12022_REG_SC] = bin2bcd(tm->tm_sec);
0206     buf[ISL12022_REG_MN] = bin2bcd(tm->tm_min);
0207     buf[ISL12022_REG_HR] = bin2bcd(tm->tm_hour) | ISL12022_HR_MIL;
0208 
0209     buf[ISL12022_REG_DT] = bin2bcd(tm->tm_mday);
0210 
0211     /* month, 1 - 12 */
0212     buf[ISL12022_REG_MO] = bin2bcd(tm->tm_mon + 1);
0213 
0214     /* year and century */
0215     buf[ISL12022_REG_YR] = bin2bcd(tm->tm_year % 100);
0216 
0217     buf[ISL12022_REG_DW] = tm->tm_wday & 0x07;
0218 
0219     /* write register's data */
0220     for (i = 0; i < ARRAY_SIZE(buf); i++) {
0221         ret = isl12022_write_reg(client, ISL12022_REG_SC + i,
0222                      buf[ISL12022_REG_SC + i]);
0223         if (ret)
0224             return -EIO;
0225     }
0226 
0227     return 0;
0228 }
0229 
0230 static const struct rtc_class_ops isl12022_rtc_ops = {
0231     .read_time  = isl12022_rtc_read_time,
0232     .set_time   = isl12022_rtc_set_time,
0233 };
0234 
0235 static int isl12022_probe(struct i2c_client *client)
0236 {
0237     struct isl12022 *isl12022;
0238 
0239     if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
0240         return -ENODEV;
0241 
0242     isl12022 = devm_kzalloc(&client->dev, sizeof(struct isl12022),
0243                 GFP_KERNEL);
0244     if (!isl12022)
0245         return -ENOMEM;
0246 
0247     i2c_set_clientdata(client, isl12022);
0248 
0249     isl12022->rtc = devm_rtc_device_register(&client->dev,
0250                     isl12022_driver.driver.name,
0251                     &isl12022_rtc_ops, THIS_MODULE);
0252     return PTR_ERR_OR_ZERO(isl12022->rtc);
0253 }
0254 
0255 #ifdef CONFIG_OF
0256 static const struct of_device_id isl12022_dt_match[] = {
0257     { .compatible = "isl,isl12022" }, /* for backward compat., don't use */
0258     { .compatible = "isil,isl12022" },
0259     { },
0260 };
0261 MODULE_DEVICE_TABLE(of, isl12022_dt_match);
0262 #endif
0263 
0264 static const struct i2c_device_id isl12022_id[] = {
0265     { "isl12022", 0 },
0266     { }
0267 };
0268 MODULE_DEVICE_TABLE(i2c, isl12022_id);
0269 
0270 static struct i2c_driver isl12022_driver = {
0271     .driver     = {
0272         .name   = "rtc-isl12022",
0273 #ifdef CONFIG_OF
0274         .of_match_table = of_match_ptr(isl12022_dt_match),
0275 #endif
0276     },
0277     .probe_new  = isl12022_probe,
0278     .id_table   = isl12022_id,
0279 };
0280 
0281 module_i2c_driver(isl12022_driver);
0282 
0283 MODULE_AUTHOR("roman.fietze@telemotive.de");
0284 MODULE_DESCRIPTION("ISL 12022 RTC driver");
0285 MODULE_LICENSE("GPL");