]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/rtc/rtc-bq32k.c
Merge tag 'armsoc-for-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
[karo-tx-linux.git] / drivers / rtc / rtc-bq32k.c
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
38 struct bq32k_regs {
39         uint8_t         seconds;
40         uint8_t         minutes;
41         uint8_t         cent_hours;
42         uint8_t         day;
43         uint8_t         date;
44         uint8_t         month;
45         uint8_t         years;
46 };
47
48 static struct i2c_driver bq32k_driver;
49
50 static int bq32k_read(struct device *dev, void *data, uint8_t off, uint8_t len)
51 {
52         struct i2c_client *client = to_i2c_client(dev);
53         struct i2c_msg msgs[] = {
54                 {
55                         .addr = client->addr,
56                         .flags = 0,
57                         .len = 1,
58                         .buf = &off,
59                 }, {
60                         .addr = client->addr,
61                         .flags = I2C_M_RD,
62                         .len = len,
63                         .buf = data,
64                 }
65         };
66
67         if (i2c_transfer(client->adapter, msgs, 2) == 2)
68                 return 0;
69
70         return -EIO;
71 }
72
73 static int bq32k_write(struct device *dev, void *data, uint8_t off, uint8_t len)
74 {
75         struct i2c_client *client = to_i2c_client(dev);
76         uint8_t buffer[len + 1];
77
78         buffer[0] = off;
79         memcpy(&buffer[1], data, len);
80
81         if (i2c_master_send(client, buffer, len + 1) == len + 1)
82                 return 0;
83
84         return -EIO;
85 }
86
87 static int bq32k_rtc_read_time(struct device *dev, struct rtc_time *tm)
88 {
89         struct bq32k_regs regs;
90         int error;
91
92         error = bq32k_read(dev, &regs, 0, sizeof(regs));
93         if (error)
94                 return error;
95
96         tm->tm_sec = bcd2bin(regs.seconds & BQ32K_SECONDS_MASK);
97         tm->tm_min = bcd2bin(regs.minutes & BQ32K_SECONDS_MASK);
98         tm->tm_hour = bcd2bin(regs.cent_hours & BQ32K_HOURS_MASK);
99         tm->tm_mday = bcd2bin(regs.date);
100         tm->tm_wday = bcd2bin(regs.day) - 1;
101         tm->tm_mon = bcd2bin(regs.month) - 1;
102         tm->tm_year = bcd2bin(regs.years) +
103                                 ((regs.cent_hours & BQ32K_CENT) ? 100 : 0);
104
105         return rtc_valid_tm(tm);
106 }
107
108 static int bq32k_rtc_set_time(struct device *dev, struct rtc_time *tm)
109 {
110         struct bq32k_regs regs;
111
112         regs.seconds = bin2bcd(tm->tm_sec);
113         regs.minutes = bin2bcd(tm->tm_min);
114         regs.cent_hours = bin2bcd(tm->tm_hour) | BQ32K_CENT_EN;
115         regs.day = bin2bcd(tm->tm_wday + 1);
116         regs.date = bin2bcd(tm->tm_mday);
117         regs.month = bin2bcd(tm->tm_mon + 1);
118
119         if (tm->tm_year >= 100) {
120                 regs.cent_hours |= BQ32K_CENT;
121                 regs.years = bin2bcd(tm->tm_year - 100);
122         } else
123                 regs.years = bin2bcd(tm->tm_year);
124
125         return bq32k_write(dev, &regs, 0, sizeof(regs));
126 }
127
128 static const struct rtc_class_ops bq32k_rtc_ops = {
129         .read_time      = bq32k_rtc_read_time,
130         .set_time       = bq32k_rtc_set_time,
131 };
132
133 static int trickle_charger_of_init(struct device *dev, struct device_node *node)
134 {
135         unsigned char reg;
136         int error;
137         u32 ohms = 0;
138
139         if (of_property_read_u32(node, "trickle-resistor-ohms" , &ohms))
140                 return 0;
141
142         switch (ohms) {
143         case 180+940:
144                 /*
145                  * TCHE[3:0] == 0x05, TCH2 == 1, TCFE == 0 (charging
146                  * over diode and 940ohm resistor)
147                  */
148
149                 if (of_property_read_bool(node, "trickle-diode-disable")) {
150                         dev_err(dev, "diode and resistor mismatch\n");
151                         return -EINVAL;
152                 }
153                 reg = 0x05;
154                 break;
155
156         case 180+20000:
157                 /* diode disabled */
158
159                 if (!of_property_read_bool(node, "trickle-diode-disable")) {
160                         dev_err(dev, "bq32k: diode and resistor mismatch\n");
161                         return -EINVAL;
162                 }
163                 reg = 0x45;
164                 break;
165
166         default:
167                 dev_err(dev, "invalid resistor value (%d)\n", ohms);
168                 return -EINVAL;
169         }
170
171         error = bq32k_write(dev, &reg, BQ32K_CFG2, 1);
172         if (error)
173                 return error;
174
175         reg = 0x20;
176         error = bq32k_write(dev, &reg, BQ32K_TCH2, 1);
177         if (error)
178                 return error;
179
180         dev_info(dev, "Enabled trickle RTC battery charge.\n");
181         return 0;
182 }
183
184 static int bq32k_probe(struct i2c_client *client,
185                                 const struct i2c_device_id *id)
186 {
187         struct device *dev = &client->dev;
188         struct rtc_device *rtc;
189         uint8_t reg;
190         int error;
191
192         if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
193                 return -ENODEV;
194
195         /* Check Oscillator Stop flag */
196         error = bq32k_read(dev, &reg, BQ32K_SECONDS, 1);
197         if (!error && (reg & BQ32K_STOP)) {
198                 dev_warn(dev, "Oscillator was halted. Restarting...\n");
199                 reg &= ~BQ32K_STOP;
200                 error = bq32k_write(dev, &reg, BQ32K_SECONDS, 1);
201         }
202         if (error)
203                 return error;
204
205         /* Check Oscillator Failure flag */
206         error = bq32k_read(dev, &reg, BQ32K_MINUTES, 1);
207         if (!error && (reg & BQ32K_OF)) {
208                 dev_warn(dev, "Oscillator Failure. Check RTC battery.\n");
209                 reg &= ~BQ32K_OF;
210                 error = bq32k_write(dev, &reg, BQ32K_MINUTES, 1);
211         }
212         if (error)
213                 return error;
214
215         if (client && client->dev.of_node)
216                 trickle_charger_of_init(dev, client->dev.of_node);
217
218         rtc = devm_rtc_device_register(&client->dev, bq32k_driver.driver.name,
219                                                 &bq32k_rtc_ops, THIS_MODULE);
220         if (IS_ERR(rtc))
221                 return PTR_ERR(rtc);
222
223         i2c_set_clientdata(client, rtc);
224
225         return 0;
226 }
227
228 static const struct i2c_device_id bq32k_id[] = {
229         { "bq32000", 0 },
230         { }
231 };
232 MODULE_DEVICE_TABLE(i2c, bq32k_id);
233
234 static struct i2c_driver bq32k_driver = {
235         .driver = {
236                 .name   = "bq32k",
237                 .owner  = THIS_MODULE,
238         },
239         .probe          = bq32k_probe,
240         .id_table       = bq32k_id,
241 };
242
243 module_i2c_driver(bq32k_driver);
244
245 MODULE_AUTHOR("Semihalf, Piotr Ziecik <kosmo@semihalf.com>");
246 MODULE_DESCRIPTION("TI BQ32000 I2C RTC driver");
247 MODULE_LICENSE("GPL");