Merge tag 'drm-next-2019-07-19' of git://anongit.freedesktop.org/drm/drm
[linux-2.6-microblaze.git] / drivers / rtc / rtc-pcf8523.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2012 Avionic Design GmbH
4  */
5
6 #include <linux/bcd.h>
7 #include <linux/i2c.h>
8 #include <linux/module.h>
9 #include <linux/rtc.h>
10 #include <linux/of.h>
11
12 #define DRIVER_NAME "rtc-pcf8523"
13
14 #define REG_CONTROL1 0x00
15 #define REG_CONTROL1_CAP_SEL (1 << 7)
16 #define REG_CONTROL1_STOP    (1 << 5)
17
18 #define REG_CONTROL3 0x02
19 #define REG_CONTROL3_PM_BLD (1 << 7) /* battery low detection disabled */
20 #define REG_CONTROL3_PM_VDD (1 << 6) /* switch-over disabled */
21 #define REG_CONTROL3_PM_DSM (1 << 5) /* direct switching mode */
22 #define REG_CONTROL3_PM_MASK 0xe0
23 #define REG_CONTROL3_BLF (1 << 2) /* battery low bit, read-only */
24
25 #define REG_SECONDS  0x03
26 #define REG_SECONDS_OS (1 << 7)
27
28 #define REG_MINUTES  0x04
29 #define REG_HOURS    0x05
30 #define REG_DAYS     0x06
31 #define REG_WEEKDAYS 0x07
32 #define REG_MONTHS   0x08
33 #define REG_YEARS    0x09
34
35 #define REG_OFFSET   0x0e
36 #define REG_OFFSET_MODE BIT(7)
37
38 struct pcf8523 {
39         struct rtc_device *rtc;
40 };
41
42 static int pcf8523_read(struct i2c_client *client, u8 reg, u8 *valuep)
43 {
44         struct i2c_msg msgs[2];
45         u8 value = 0;
46         int err;
47
48         msgs[0].addr = client->addr;
49         msgs[0].flags = 0;
50         msgs[0].len = sizeof(reg);
51         msgs[0].buf = &reg;
52
53         msgs[1].addr = client->addr;
54         msgs[1].flags = I2C_M_RD;
55         msgs[1].len = sizeof(value);
56         msgs[1].buf = &value;
57
58         err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
59         if (err < 0)
60                 return err;
61
62         *valuep = value;
63
64         return 0;
65 }
66
67 static int pcf8523_write(struct i2c_client *client, u8 reg, u8 value)
68 {
69         u8 buffer[2] = { reg, value };
70         struct i2c_msg msg;
71         int err;
72
73         msg.addr = client->addr;
74         msg.flags = 0;
75         msg.len = sizeof(buffer);
76         msg.buf = buffer;
77
78         err = i2c_transfer(client->adapter, &msg, 1);
79         if (err < 0)
80                 return err;
81
82         return 0;
83 }
84
85 static int pcf8523_voltage_low(struct i2c_client *client)
86 {
87         u8 value;
88         int err;
89
90         err = pcf8523_read(client, REG_CONTROL3, &value);
91         if (err < 0)
92                 return err;
93
94         return !!(value & REG_CONTROL3_BLF);
95 }
96
97 static int pcf8523_load_capacitance(struct i2c_client *client)
98 {
99         u32 load;
100         u8 value;
101         int err;
102
103         err = pcf8523_read(client, REG_CONTROL1, &value);
104         if (err < 0)
105                 return err;
106
107         load = 12500;
108         of_property_read_u32(client->dev.of_node, "quartz-load-femtofarads",
109                              &load);
110
111         switch (load) {
112         default:
113                 dev_warn(&client->dev, "Unknown quartz-load-femtofarads value: %d. Assuming 12500",
114                          load);
115                 /* fall through */
116         case 12500:
117                 value |= REG_CONTROL1_CAP_SEL;
118                 break;
119         case 7000:
120                 value &= ~REG_CONTROL1_CAP_SEL;
121                 break;
122         }
123
124         err = pcf8523_write(client, REG_CONTROL1, value);
125
126         return err;
127 }
128
129 static int pcf8523_set_pm(struct i2c_client *client, u8 pm)
130 {
131         u8 value;
132         int err;
133
134         err = pcf8523_read(client, REG_CONTROL3, &value);
135         if (err < 0)
136                 return err;
137
138         value = (value & ~REG_CONTROL3_PM_MASK) | pm;
139
140         err = pcf8523_write(client, REG_CONTROL3, value);
141         if (err < 0)
142                 return err;
143
144         return 0;
145 }
146
147 static int pcf8523_stop_rtc(struct i2c_client *client)
148 {
149         u8 value;
150         int err;
151
152         err = pcf8523_read(client, REG_CONTROL1, &value);
153         if (err < 0)
154                 return err;
155
156         value |= REG_CONTROL1_STOP;
157
158         err = pcf8523_write(client, REG_CONTROL1, value);
159         if (err < 0)
160                 return err;
161
162         return 0;
163 }
164
165 static int pcf8523_start_rtc(struct i2c_client *client)
166 {
167         u8 value;
168         int err;
169
170         err = pcf8523_read(client, REG_CONTROL1, &value);
171         if (err < 0)
172                 return err;
173
174         value &= ~REG_CONTROL1_STOP;
175
176         err = pcf8523_write(client, REG_CONTROL1, value);
177         if (err < 0)
178                 return err;
179
180         return 0;
181 }
182
183 static int pcf8523_rtc_read_time(struct device *dev, struct rtc_time *tm)
184 {
185         struct i2c_client *client = to_i2c_client(dev);
186         u8 start = REG_SECONDS, regs[7];
187         struct i2c_msg msgs[2];
188         int err;
189
190         err = pcf8523_voltage_low(client);
191         if (err < 0) {
192                 return err;
193         } else if (err > 0) {
194                 dev_err(dev, "low voltage detected, time is unreliable\n");
195                 return -EINVAL;
196         }
197
198         msgs[0].addr = client->addr;
199         msgs[0].flags = 0;
200         msgs[0].len = 1;
201         msgs[0].buf = &start;
202
203         msgs[1].addr = client->addr;
204         msgs[1].flags = I2C_M_RD;
205         msgs[1].len = sizeof(regs);
206         msgs[1].buf = regs;
207
208         err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
209         if (err < 0)
210                 return err;
211
212         if (regs[0] & REG_SECONDS_OS)
213                 return -EINVAL;
214
215         tm->tm_sec = bcd2bin(regs[0] & 0x7f);
216         tm->tm_min = bcd2bin(regs[1] & 0x7f);
217         tm->tm_hour = bcd2bin(regs[2] & 0x3f);
218         tm->tm_mday = bcd2bin(regs[3] & 0x3f);
219         tm->tm_wday = regs[4] & 0x7;
220         tm->tm_mon = bcd2bin(regs[5] & 0x1f) - 1;
221         tm->tm_year = bcd2bin(regs[6]) + 100;
222
223         return 0;
224 }
225
226 static int pcf8523_rtc_set_time(struct device *dev, struct rtc_time *tm)
227 {
228         struct i2c_client *client = to_i2c_client(dev);
229         struct i2c_msg msg;
230         u8 regs[8];
231         int err;
232
233         /*
234          * The hardware can only store values between 0 and 99 in it's YEAR
235          * register (with 99 overflowing to 0 on increment).
236          * After 2100-02-28 we could start interpreting the year to be in the
237          * interval [2100, 2199], but there is no path to switch in a smooth way
238          * because the chip handles YEAR=0x00 (and the out-of-spec
239          * YEAR=0xa0) as a leap year, but 2100 isn't.
240          */
241         if (tm->tm_year < 100 || tm->tm_year >= 200)
242                 return -EINVAL;
243
244         err = pcf8523_stop_rtc(client);
245         if (err < 0)
246                 return err;
247
248         regs[0] = REG_SECONDS;
249         /* This will purposely overwrite REG_SECONDS_OS */
250         regs[1] = bin2bcd(tm->tm_sec);
251         regs[2] = bin2bcd(tm->tm_min);
252         regs[3] = bin2bcd(tm->tm_hour);
253         regs[4] = bin2bcd(tm->tm_mday);
254         regs[5] = tm->tm_wday;
255         regs[6] = bin2bcd(tm->tm_mon + 1);
256         regs[7] = bin2bcd(tm->tm_year - 100);
257
258         msg.addr = client->addr;
259         msg.flags = 0;
260         msg.len = sizeof(regs);
261         msg.buf = regs;
262
263         err = i2c_transfer(client->adapter, &msg, 1);
264         if (err < 0) {
265                 /*
266                  * If the time cannot be set, restart the RTC anyway. Note
267                  * that errors are ignored if the RTC cannot be started so
268                  * that we have a chance to propagate the original error.
269                  */
270                 pcf8523_start_rtc(client);
271                 return err;
272         }
273
274         return pcf8523_start_rtc(client);
275 }
276
277 #ifdef CONFIG_RTC_INTF_DEV
278 static int pcf8523_rtc_ioctl(struct device *dev, unsigned int cmd,
279                              unsigned long arg)
280 {
281         struct i2c_client *client = to_i2c_client(dev);
282         int ret;
283
284         switch (cmd) {
285         case RTC_VL_READ:
286                 ret = pcf8523_voltage_low(client);
287                 if (ret < 0)
288                         return ret;
289
290                 if (copy_to_user((void __user *)arg, &ret, sizeof(int)))
291                         return -EFAULT;
292
293                 return 0;
294         default:
295                 return -ENOIOCTLCMD;
296         }
297 }
298 #else
299 #define pcf8523_rtc_ioctl NULL
300 #endif
301
302 static int pcf8523_rtc_read_offset(struct device *dev, long *offset)
303 {
304         struct i2c_client *client = to_i2c_client(dev);
305         int err;
306         u8 value;
307         s8 val;
308
309         err = pcf8523_read(client, REG_OFFSET, &value);
310         if (err < 0)
311                 return err;
312
313         /* sign extend the 7-bit offset value */
314         val = value << 1;
315         *offset = (value & REG_OFFSET_MODE ? 4069 : 4340) * (val >> 1);
316
317         return 0;
318 }
319
320 static int pcf8523_rtc_set_offset(struct device *dev, long offset)
321 {
322         struct i2c_client *client = to_i2c_client(dev);
323         long reg_m0, reg_m1;
324         u8 value;
325
326         reg_m0 = clamp(DIV_ROUND_CLOSEST(offset, 4340), -64L, 63L);
327         reg_m1 = clamp(DIV_ROUND_CLOSEST(offset, 4069), -64L, 63L);
328
329         if (abs(reg_m0 * 4340 - offset) < abs(reg_m1 * 4069 - offset))
330                 value = reg_m0 & 0x7f;
331         else
332                 value = (reg_m1 & 0x7f) | REG_OFFSET_MODE;
333
334         return pcf8523_write(client, REG_OFFSET, value);
335 }
336
337 static const struct rtc_class_ops pcf8523_rtc_ops = {
338         .read_time = pcf8523_rtc_read_time,
339         .set_time = pcf8523_rtc_set_time,
340         .ioctl = pcf8523_rtc_ioctl,
341         .read_offset = pcf8523_rtc_read_offset,
342         .set_offset = pcf8523_rtc_set_offset,
343 };
344
345 static int pcf8523_probe(struct i2c_client *client,
346                          const struct i2c_device_id *id)
347 {
348         struct pcf8523 *pcf;
349         int err;
350
351         if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
352                 return -ENODEV;
353
354         pcf = devm_kzalloc(&client->dev, sizeof(*pcf), GFP_KERNEL);
355         if (!pcf)
356                 return -ENOMEM;
357
358         err = pcf8523_load_capacitance(client);
359         if (err < 0)
360                 dev_warn(&client->dev, "failed to set xtal load capacitance: %d",
361                          err);
362
363         err = pcf8523_set_pm(client, 0);
364         if (err < 0)
365                 return err;
366
367         pcf->rtc = devm_rtc_device_register(&client->dev, DRIVER_NAME,
368                                        &pcf8523_rtc_ops, THIS_MODULE);
369         if (IS_ERR(pcf->rtc))
370                 return PTR_ERR(pcf->rtc);
371
372         i2c_set_clientdata(client, pcf);
373
374         return 0;
375 }
376
377 static const struct i2c_device_id pcf8523_id[] = {
378         { "pcf8523", 0 },
379         { }
380 };
381 MODULE_DEVICE_TABLE(i2c, pcf8523_id);
382
383 #ifdef CONFIG_OF
384 static const struct of_device_id pcf8523_of_match[] = {
385         { .compatible = "nxp,pcf8523" },
386         { .compatible = "microcrystal,rv8523" },
387         { }
388 };
389 MODULE_DEVICE_TABLE(of, pcf8523_of_match);
390 #endif
391
392 static struct i2c_driver pcf8523_driver = {
393         .driver = {
394                 .name = DRIVER_NAME,
395                 .of_match_table = of_match_ptr(pcf8523_of_match),
396         },
397         .probe = pcf8523_probe,
398         .id_table = pcf8523_id,
399 };
400 module_i2c_driver(pcf8523_driver);
401
402 MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>");
403 MODULE_DESCRIPTION("NXP PCF8523 RTC driver");
404 MODULE_LICENSE("GPL v2");