linux/drivers/rtc/rtc-bq32k.c
<<
>>
Prefs
   1/*
   2 * Driver for TI BQ32000 RTC.
   3 *
   4 * Copyright (C) 2009 Semihalf.
   5 * Copyright (C) 2014 Pavel Machek <pavel@denx.de>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation.
  10 *
  11 * You can get hardware description at
  12 * http://www.ti.com/lit/ds/symlink/bq32000.pdf
  13 */
  14
  15#include <linux/module.h>
  16#include <linux/i2c.h>
  17#include <linux/rtc.h>
  18#include <linux/init.h>
  19#include <linux/errno.h>
  20#include <linux/bcd.h>
  21
  22#define BQ32K_SECONDS           0x00    /* Seconds register address */
  23#define BQ32K_SECONDS_MASK      0x7F    /* Mask over seconds value */
  24#define BQ32K_STOP              0x80    /* Oscillator Stop flat */
  25
  26#define BQ32K_MINUTES           0x01    /* Minutes register address */
  27#define BQ32K_MINUTES_MASK      0x7F    /* Mask over minutes value */
  28#define BQ32K_OF                0x80    /* Oscillator Failure flag */
  29
  30#define BQ32K_HOURS_MASK        0x3F    /* Mask over hours value */
  31#define BQ32K_CENT              0x40    /* Century flag */
  32#define BQ32K_CENT_EN           0x80    /* Century flag enable bit */
  33
  34#define BQ32K_CALIBRATION       0x07    /* CAL_CFG1, calibration and control */
  35#define BQ32K_TCH2              0x08    /* Trickle charge enable */
  36#define BQ32K_CFG2              0x09    /* Trickle charger control */
  37#define BQ32K_TCFE              BIT(6)  /* Trickle charge FET bypass */
  38
  39#define MAX_LEN                 10      /* Maximum number of consecutive
  40                                         * register for this particular RTC.
  41                                         */
  42
  43struct bq32k_regs {
  44        uint8_t         seconds;
  45        uint8_t         minutes;
  46        uint8_t         cent_hours;
  47        uint8_t         day;
  48        uint8_t         date;
  49        uint8_t         month;
  50        uint8_t         years;
  51};
  52
  53static struct i2c_driver bq32k_driver;
  54
  55static int bq32k_read(struct device *dev, void *data, uint8_t off, uint8_t len)
  56{
  57        struct i2c_client *client = to_i2c_client(dev);
  58        struct i2c_msg msgs[] = {
  59                {
  60                        .addr = client->addr,
  61                        .flags = 0,
  62                        .len = 1,
  63                        .buf = &off,
  64                }, {
  65                        .addr = client->addr,
  66                        .flags = I2C_M_RD,
  67                        .len = len,
  68                        .buf = data,
  69                }
  70        };
  71
  72        if (i2c_transfer(client->adapter, msgs, 2) == 2)
  73                return 0;
  74
  75        return -EIO;
  76}
  77
  78static int bq32k_write(struct device *dev, void *data, uint8_t off, uint8_t len)
  79{
  80        struct i2c_client *client = to_i2c_client(dev);
  81        uint8_t buffer[MAX_LEN + 1];
  82
  83        buffer[0] = off;
  84        memcpy(&buffer[1], data, len);
  85
  86        if (i2c_master_send(client, buffer, len + 1) == len + 1)
  87                return 0;
  88
  89        return -EIO;
  90}
  91
  92static int bq32k_rtc_read_time(struct device *dev, struct rtc_time *tm)
  93{
  94        struct bq32k_regs regs;
  95        int error;
  96
  97        error = bq32k_read(dev, &regs, 0, sizeof(regs));
  98        if (error)
  99                return error;
 100
 101        /*
 102         * In case of oscillator failure, the register contents should be
 103         * considered invalid. The flag is cleared the next time the RTC is set.
 104         */
 105        if (regs.minutes & BQ32K_OF)
 106                return -EINVAL;
 107
 108        tm->tm_sec = bcd2bin(regs.seconds & BQ32K_SECONDS_MASK);
 109        tm->tm_min = bcd2bin(regs.minutes & BQ32K_MINUTES_MASK);
 110        tm->tm_hour = bcd2bin(regs.cent_hours & BQ32K_HOURS_MASK);
 111        tm->tm_mday = bcd2bin(regs.date);
 112        tm->tm_wday = bcd2bin(regs.day) - 1;
 113        tm->tm_mon = bcd2bin(regs.month) - 1;
 114        tm->tm_year = bcd2bin(regs.years) +
 115                                ((regs.cent_hours & BQ32K_CENT) ? 100 : 0);
 116
 117        return 0;
 118}
 119
 120static int bq32k_rtc_set_time(struct device *dev, struct rtc_time *tm)
 121{
 122        struct bq32k_regs regs;
 123
 124        regs.seconds = bin2bcd(tm->tm_sec);
 125        regs.minutes = bin2bcd(tm->tm_min);
 126        regs.cent_hours = bin2bcd(tm->tm_hour) | BQ32K_CENT_EN;
 127        regs.day = bin2bcd(tm->tm_wday + 1);
 128        regs.date = bin2bcd(tm->tm_mday);
 129        regs.month = bin2bcd(tm->tm_mon + 1);
 130
 131        if (tm->tm_year >= 100) {
 132                regs.cent_hours |= BQ32K_CENT;
 133                regs.years = bin2bcd(tm->tm_year - 100);
 134        } else
 135                regs.years = bin2bcd(tm->tm_year);
 136
 137        return bq32k_write(dev, &regs, 0, sizeof(regs));
 138}
 139
 140static const struct rtc_class_ops bq32k_rtc_ops = {
 141        .read_time      = bq32k_rtc_read_time,
 142        .set_time       = bq32k_rtc_set_time,
 143};
 144
 145static int trickle_charger_of_init(struct device *dev, struct device_node *node)
 146{
 147        unsigned char reg;
 148        int error;
 149        u32 ohms = 0;
 150
 151        if (of_property_read_u32(node, "trickle-resistor-ohms" , &ohms))
 152                return 0;
 153
 154        switch (ohms) {
 155        case 180+940:
 156                /*
 157                 * TCHE[3:0] == 0x05, TCH2 == 1, TCFE == 0 (charging
 158                 * over diode and 940ohm resistor)
 159                 */
 160
 161                if (of_property_read_bool(node, "trickle-diode-disable")) {
 162                        dev_err(dev, "diode and resistor mismatch\n");
 163                        return -EINVAL;
 164                }
 165                reg = 0x05;
 166                break;
 167
 168        case 180+20000:
 169                /* diode disabled */
 170
 171                if (!of_property_read_bool(node, "trickle-diode-disable")) {
 172                        dev_err(dev, "bq32k: diode and resistor mismatch\n");
 173                        return -EINVAL;
 174                }
 175                reg = 0x45;
 176                break;
 177
 178        default:
 179                dev_err(dev, "invalid resistor value (%d)\n", ohms);
 180                return -EINVAL;
 181        }
 182
 183        error = bq32k_write(dev, &reg, BQ32K_CFG2, 1);
 184        if (error)
 185                return error;
 186
 187        reg = 0x20;
 188        error = bq32k_write(dev, &reg, BQ32K_TCH2, 1);
 189        if (error)
 190                return error;
 191
 192        dev_info(dev, "Enabled trickle RTC battery charge.\n");
 193        return 0;
 194}
 195
 196static ssize_t bq32k_sysfs_show_tricklecharge_bypass(struct device *dev,
 197                                               struct device_attribute *attr,
 198                                               char *buf)
 199{
 200        int reg, error;
 201
 202        error = bq32k_read(dev, &reg, BQ32K_CFG2, 1);
 203        if (error)
 204                return error;
 205
 206        return sprintf(buf, "%d\n", (reg & BQ32K_TCFE) ? 1 : 0);
 207}
 208
 209static ssize_t bq32k_sysfs_store_tricklecharge_bypass(struct device *dev,
 210                                                struct device_attribute *attr,
 211                                                const char *buf, size_t count)
 212{
 213        int reg, enable, error;
 214
 215        if (kstrtoint(buf, 0, &enable))
 216                return -EINVAL;
 217
 218        error = bq32k_read(dev, &reg, BQ32K_CFG2, 1);
 219        if (error)
 220                return error;
 221
 222        if (enable) {
 223                reg |= BQ32K_TCFE;
 224                error = bq32k_write(dev, &reg, BQ32K_CFG2, 1);
 225                if (error)
 226                        return error;
 227
 228                dev_info(dev, "Enabled trickle charge FET bypass.\n");
 229        } else {
 230                reg &= ~BQ32K_TCFE;
 231                error = bq32k_write(dev, &reg, BQ32K_CFG2, 1);
 232                if (error)
 233                        return error;
 234
 235                dev_info(dev, "Disabled trickle charge FET bypass.\n");
 236        }
 237
 238        return count;
 239}
 240
 241static DEVICE_ATTR(trickle_charge_bypass, 0644,
 242                   bq32k_sysfs_show_tricklecharge_bypass,
 243                   bq32k_sysfs_store_tricklecharge_bypass);
 244
 245static int bq32k_sysfs_register(struct device *dev)
 246{
 247        return device_create_file(dev, &dev_attr_trickle_charge_bypass);
 248}
 249
 250static void bq32k_sysfs_unregister(struct device *dev)
 251{
 252        device_remove_file(dev, &dev_attr_trickle_charge_bypass);
 253}
 254
 255static int bq32k_probe(struct i2c_client *client,
 256                                const struct i2c_device_id *id)
 257{
 258        struct device *dev = &client->dev;
 259        struct rtc_device *rtc;
 260        uint8_t reg;
 261        int error;
 262
 263        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
 264                return -ENODEV;
 265
 266        /* Check Oscillator Stop flag */
 267        error = bq32k_read(dev, &reg, BQ32K_SECONDS, 1);
 268        if (!error && (reg & BQ32K_STOP)) {
 269                dev_warn(dev, "Oscillator was halted. Restarting...\n");
 270                reg &= ~BQ32K_STOP;
 271                error = bq32k_write(dev, &reg, BQ32K_SECONDS, 1);
 272        }
 273        if (error)
 274                return error;
 275
 276        /* Check Oscillator Failure flag */
 277        error = bq32k_read(dev, &reg, BQ32K_MINUTES, 1);
 278        if (error)
 279                return error;
 280        if (reg & BQ32K_OF)
 281                dev_warn(dev, "Oscillator Failure. Check RTC battery.\n");
 282
 283        if (client->dev.of_node)
 284                trickle_charger_of_init(dev, client->dev.of_node);
 285
 286        rtc = devm_rtc_device_register(&client->dev, bq32k_driver.driver.name,
 287                                                &bq32k_rtc_ops, THIS_MODULE);
 288        if (IS_ERR(rtc))
 289                return PTR_ERR(rtc);
 290
 291        error = bq32k_sysfs_register(&client->dev);
 292        if (error) {
 293                dev_err(&client->dev,
 294                        "Unable to create sysfs entries for rtc bq32000\n");
 295                return error;
 296        }
 297
 298
 299        i2c_set_clientdata(client, rtc);
 300
 301        return 0;
 302}
 303
 304static int bq32k_remove(struct i2c_client *client)
 305{
 306        bq32k_sysfs_unregister(&client->dev);
 307
 308        return 0;
 309}
 310
 311static const struct i2c_device_id bq32k_id[] = {
 312        { "bq32000", 0 },
 313        { }
 314};
 315MODULE_DEVICE_TABLE(i2c, bq32k_id);
 316
 317static const struct of_device_id bq32k_of_match[] = {
 318        { .compatible = "ti,bq32000" },
 319        { }
 320};
 321MODULE_DEVICE_TABLE(of, bq32k_of_match);
 322
 323static struct i2c_driver bq32k_driver = {
 324        .driver = {
 325                .name   = "bq32k",
 326                .of_match_table = of_match_ptr(bq32k_of_match),
 327        },
 328        .probe          = bq32k_probe,
 329        .remove         = bq32k_remove,
 330        .id_table       = bq32k_id,
 331};
 332
 333module_i2c_driver(bq32k_driver);
 334
 335MODULE_AUTHOR("Semihalf, Piotr Ziecik <kosmo@semihalf.com>");
 336MODULE_DESCRIPTION("TI BQ32000 I2C RTC driver");
 337MODULE_LICENSE("GPL");
 338