Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Driver for TI BQ32000 RTC.
0004  *
0005  * Copyright (C) 2009 Semihalf.
0006  * Copyright (C) 2014 Pavel Machek <pavel@denx.de>
0007  *
0008  * You can get hardware description at
0009  * https://www.ti.com/lit/ds/symlink/bq32000.pdf
0010  */
0011 
0012 #include <linux/module.h>
0013 #include <linux/i2c.h>
0014 #include <linux/rtc.h>
0015 #include <linux/init.h>
0016 #include <linux/errno.h>
0017 #include <linux/bcd.h>
0018 
0019 #define BQ32K_SECONDS       0x00    /* Seconds register address */
0020 #define BQ32K_SECONDS_MASK  0x7F    /* Mask over seconds value */
0021 #define BQ32K_STOP      0x80    /* Oscillator Stop flat */
0022 
0023 #define BQ32K_MINUTES       0x01    /* Minutes register address */
0024 #define BQ32K_MINUTES_MASK  0x7F    /* Mask over minutes value */
0025 #define BQ32K_OF        0x80    /* Oscillator Failure flag */
0026 
0027 #define BQ32K_HOURS_MASK    0x3F    /* Mask over hours value */
0028 #define BQ32K_CENT      0x40    /* Century flag */
0029 #define BQ32K_CENT_EN       0x80    /* Century flag enable bit */
0030 
0031 #define BQ32K_CALIBRATION   0x07    /* CAL_CFG1, calibration and control */
0032 #define BQ32K_TCH2      0x08    /* Trickle charge enable */
0033 #define BQ32K_CFG2      0x09    /* Trickle charger control */
0034 #define BQ32K_TCFE      BIT(6)  /* Trickle charge FET bypass */
0035 
0036 #define MAX_LEN         10  /* Maximum number of consecutive
0037                      * register for this particular RTC.
0038                      */
0039 
0040 struct bq32k_regs {
0041     uint8_t     seconds;
0042     uint8_t     minutes;
0043     uint8_t     cent_hours;
0044     uint8_t     day;
0045     uint8_t     date;
0046     uint8_t     month;
0047     uint8_t     years;
0048 };
0049 
0050 static struct i2c_driver bq32k_driver;
0051 
0052 static int bq32k_read(struct device *dev, void *data, uint8_t off, uint8_t len)
0053 {
0054     struct i2c_client *client = to_i2c_client(dev);
0055     struct i2c_msg msgs[] = {
0056         {
0057             .addr = client->addr,
0058             .flags = 0,
0059             .len = 1,
0060             .buf = &off,
0061         }, {
0062             .addr = client->addr,
0063             .flags = I2C_M_RD,
0064             .len = len,
0065             .buf = data,
0066         }
0067     };
0068 
0069     if (i2c_transfer(client->adapter, msgs, 2) == 2)
0070         return 0;
0071 
0072     return -EIO;
0073 }
0074 
0075 static int bq32k_write(struct device *dev, void *data, uint8_t off, uint8_t len)
0076 {
0077     struct i2c_client *client = to_i2c_client(dev);
0078     uint8_t buffer[MAX_LEN + 1];
0079 
0080     buffer[0] = off;
0081     memcpy(&buffer[1], data, len);
0082 
0083     if (i2c_master_send(client, buffer, len + 1) == len + 1)
0084         return 0;
0085 
0086     return -EIO;
0087 }
0088 
0089 static int bq32k_rtc_read_time(struct device *dev, struct rtc_time *tm)
0090 {
0091     struct bq32k_regs regs;
0092     int error;
0093 
0094     error = bq32k_read(dev, &regs, 0, sizeof(regs));
0095     if (error)
0096         return error;
0097 
0098     /*
0099      * In case of oscillator failure, the register contents should be
0100      * considered invalid. The flag is cleared the next time the RTC is set.
0101      */
0102     if (regs.minutes & BQ32K_OF)
0103         return -EINVAL;
0104 
0105     tm->tm_sec = bcd2bin(regs.seconds & BQ32K_SECONDS_MASK);
0106     tm->tm_min = bcd2bin(regs.minutes & BQ32K_MINUTES_MASK);
0107     tm->tm_hour = bcd2bin(regs.cent_hours & BQ32K_HOURS_MASK);
0108     tm->tm_mday = bcd2bin(regs.date);
0109     tm->tm_wday = bcd2bin(regs.day) - 1;
0110     tm->tm_mon = bcd2bin(regs.month) - 1;
0111     tm->tm_year = bcd2bin(regs.years) +
0112                 ((regs.cent_hours & BQ32K_CENT) ? 100 : 0);
0113 
0114     return 0;
0115 }
0116 
0117 static int bq32k_rtc_set_time(struct device *dev, struct rtc_time *tm)
0118 {
0119     struct bq32k_regs regs;
0120 
0121     regs.seconds = bin2bcd(tm->tm_sec);
0122     regs.minutes = bin2bcd(tm->tm_min);
0123     regs.cent_hours = bin2bcd(tm->tm_hour) | BQ32K_CENT_EN;
0124     regs.day = bin2bcd(tm->tm_wday + 1);
0125     regs.date = bin2bcd(tm->tm_mday);
0126     regs.month = bin2bcd(tm->tm_mon + 1);
0127 
0128     if (tm->tm_year >= 100) {
0129         regs.cent_hours |= BQ32K_CENT;
0130         regs.years = bin2bcd(tm->tm_year - 100);
0131     } else
0132         regs.years = bin2bcd(tm->tm_year);
0133 
0134     return bq32k_write(dev, &regs, 0, sizeof(regs));
0135 }
0136 
0137 static const struct rtc_class_ops bq32k_rtc_ops = {
0138     .read_time  = bq32k_rtc_read_time,
0139     .set_time   = bq32k_rtc_set_time,
0140 };
0141 
0142 static int trickle_charger_of_init(struct device *dev, struct device_node *node)
0143 {
0144     unsigned char reg;
0145     int error;
0146     u32 ohms = 0;
0147 
0148     if (of_property_read_u32(node, "trickle-resistor-ohms" , &ohms))
0149         return 0;
0150 
0151     switch (ohms) {
0152     case 180+940:
0153         /*
0154          * TCHE[3:0] == 0x05, TCH2 == 1, TCFE == 0 (charging
0155          * over diode and 940ohm resistor)
0156          */
0157 
0158         if (of_property_read_bool(node, "trickle-diode-disable")) {
0159             dev_err(dev, "diode and resistor mismatch\n");
0160             return -EINVAL;
0161         }
0162         reg = 0x05;
0163         break;
0164 
0165     case 180+20000:
0166         /* diode disabled */
0167 
0168         if (!of_property_read_bool(node, "trickle-diode-disable")) {
0169             dev_err(dev, "bq32k: diode and resistor mismatch\n");
0170             return -EINVAL;
0171         }
0172         reg = 0x45;
0173         break;
0174 
0175     default:
0176         dev_err(dev, "invalid resistor value (%d)\n", ohms);
0177         return -EINVAL;
0178     }
0179 
0180     error = bq32k_write(dev, &reg, BQ32K_CFG2, 1);
0181     if (error)
0182         return error;
0183 
0184     reg = 0x20;
0185     error = bq32k_write(dev, &reg, BQ32K_TCH2, 1);
0186     if (error)
0187         return error;
0188 
0189     dev_info(dev, "Enabled trickle RTC battery charge.\n");
0190     return 0;
0191 }
0192 
0193 static ssize_t bq32k_sysfs_show_tricklecharge_bypass(struct device *dev,
0194                            struct device_attribute *attr,
0195                            char *buf)
0196 {
0197     int reg, error;
0198 
0199     error = bq32k_read(dev, &reg, BQ32K_CFG2, 1);
0200     if (error)
0201         return error;
0202 
0203     return sprintf(buf, "%d\n", (reg & BQ32K_TCFE) ? 1 : 0);
0204 }
0205 
0206 static ssize_t bq32k_sysfs_store_tricklecharge_bypass(struct device *dev,
0207                         struct device_attribute *attr,
0208                         const char *buf, size_t count)
0209 {
0210     int reg, enable, error;
0211 
0212     if (kstrtoint(buf, 0, &enable))
0213         return -EINVAL;
0214 
0215     error = bq32k_read(dev, &reg, BQ32K_CFG2, 1);
0216     if (error)
0217         return error;
0218 
0219     if (enable) {
0220         reg |= BQ32K_TCFE;
0221         error = bq32k_write(dev, &reg, BQ32K_CFG2, 1);
0222         if (error)
0223             return error;
0224 
0225         dev_info(dev, "Enabled trickle charge FET bypass.\n");
0226     } else {
0227         reg &= ~BQ32K_TCFE;
0228         error = bq32k_write(dev, &reg, BQ32K_CFG2, 1);
0229         if (error)
0230             return error;
0231 
0232         dev_info(dev, "Disabled trickle charge FET bypass.\n");
0233     }
0234 
0235     return count;
0236 }
0237 
0238 static DEVICE_ATTR(trickle_charge_bypass, 0644,
0239            bq32k_sysfs_show_tricklecharge_bypass,
0240            bq32k_sysfs_store_tricklecharge_bypass);
0241 
0242 static int bq32k_sysfs_register(struct device *dev)
0243 {
0244     return device_create_file(dev, &dev_attr_trickle_charge_bypass);
0245 }
0246 
0247 static void bq32k_sysfs_unregister(struct device *dev)
0248 {
0249     device_remove_file(dev, &dev_attr_trickle_charge_bypass);
0250 }
0251 
0252 static int bq32k_probe(struct i2c_client *client)
0253 {
0254     struct device *dev = &client->dev;
0255     struct rtc_device *rtc;
0256     uint8_t reg;
0257     int error;
0258 
0259     if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
0260         return -ENODEV;
0261 
0262     /* Check Oscillator Stop flag */
0263     error = bq32k_read(dev, &reg, BQ32K_SECONDS, 1);
0264     if (!error && (reg & BQ32K_STOP)) {
0265         dev_warn(dev, "Oscillator was halted. Restarting...\n");
0266         reg &= ~BQ32K_STOP;
0267         error = bq32k_write(dev, &reg, BQ32K_SECONDS, 1);
0268     }
0269     if (error)
0270         return error;
0271 
0272     /* Check Oscillator Failure flag */
0273     error = bq32k_read(dev, &reg, BQ32K_MINUTES, 1);
0274     if (error)
0275         return error;
0276     if (reg & BQ32K_OF)
0277         dev_warn(dev, "Oscillator Failure. Check RTC battery.\n");
0278 
0279     if (client->dev.of_node)
0280         trickle_charger_of_init(dev, client->dev.of_node);
0281 
0282     rtc = devm_rtc_device_register(&client->dev, bq32k_driver.driver.name,
0283                         &bq32k_rtc_ops, THIS_MODULE);
0284     if (IS_ERR(rtc))
0285         return PTR_ERR(rtc);
0286 
0287     error = bq32k_sysfs_register(&client->dev);
0288     if (error) {
0289         dev_err(&client->dev,
0290             "Unable to create sysfs entries for rtc bq32000\n");
0291         return error;
0292     }
0293 
0294 
0295     i2c_set_clientdata(client, rtc);
0296 
0297     return 0;
0298 }
0299 
0300 static int bq32k_remove(struct i2c_client *client)
0301 {
0302     bq32k_sysfs_unregister(&client->dev);
0303 
0304     return 0;
0305 }
0306 
0307 static const struct i2c_device_id bq32k_id[] = {
0308     { "bq32000", 0 },
0309     { }
0310 };
0311 MODULE_DEVICE_TABLE(i2c, bq32k_id);
0312 
0313 static const __maybe_unused struct of_device_id bq32k_of_match[] = {
0314     { .compatible = "ti,bq32000" },
0315     { }
0316 };
0317 MODULE_DEVICE_TABLE(of, bq32k_of_match);
0318 
0319 static struct i2c_driver bq32k_driver = {
0320     .driver = {
0321         .name   = "bq32k",
0322         .of_match_table = of_match_ptr(bq32k_of_match),
0323     },
0324     .probe_new  = bq32k_probe,
0325     .remove     = bq32k_remove,
0326     .id_table   = bq32k_id,
0327 };
0328 
0329 module_i2c_driver(bq32k_driver);
0330 
0331 MODULE_AUTHOR("Semihalf, Piotr Ziecik <kosmo@semihalf.com>");
0332 MODULE_DESCRIPTION("TI BQ32000 I2C RTC driver");
0333 MODULE_LICENSE("GPL");