Merge tag 'arm-soc-drivers-5.11' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / drivers / rtc / rtc-rc5t619.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * drivers/rtc/rtc-rc5t619.c
4  *
5  * Real time clock driver for RICOH RC5T619 power management chip.
6  *
7  * Copyright (C) 2019 Andreas Kemnade
8  */
9
10 #include <linux/kernel.h>
11 #include <linux/device.h>
12 #include <linux/errno.h>
13 #include <linux/init.h>
14 #include <linux/module.h>
15 #include <linux/mfd/rn5t618.h>
16 #include <linux/platform_device.h>
17 #include <linux/regmap.h>
18 #include <linux/bcd.h>
19 #include <linux/rtc.h>
20 #include <linux/slab.h>
21 #include <linux/irqdomain.h>
22
23 struct rc5t619_rtc {
24         int                     irq;
25         struct rtc_device       *rtc;
26         struct rn5t618 *rn5t618;
27 };
28
29 #define CTRL1_ALARM_ENABLED 0x40
30 #define CTRL1_24HR 0x20
31 #define CTRL1_PERIODIC_MASK 0xf
32
33 #define CTRL2_PON 0x10
34 #define CTRL2_ALARM_STATUS 0x80
35 #define CTRL2_CTFG 0x4
36 #define CTRL2_CTC 0x1
37
38 #define MONTH_CENTFLAG 0x80
39 #define HOUR_PMFLAG 0x20
40 #define MDAY_DAL_EXT 0x80
41
42 static uint8_t rtc5t619_12hour_bcd2bin(uint8_t hour)
43 {
44         if (hour & HOUR_PMFLAG) {
45                 hour = bcd2bin(hour & ~HOUR_PMFLAG);
46                 return hour == 12 ? 12 : 12 + hour;
47         }
48
49         hour = bcd2bin(hour);
50         return hour == 12 ? 0 : hour;
51 }
52
53 static uint8_t rtc5t619_12hour_bin2bcd(uint8_t hour)
54 {
55         if (!hour)
56                 return 0x12;
57
58         if (hour < 12)
59                 return bin2bcd(hour);
60
61         if (hour == 12)
62                 return 0x12 | HOUR_PMFLAG;
63
64         return bin2bcd(hour - 12) | HOUR_PMFLAG;
65 }
66
67 static int rc5t619_rtc_periodic_disable(struct device *dev)
68 {
69         struct rc5t619_rtc *rtc = dev_get_drvdata(dev);
70         int err;
71
72         /* disable function */
73         err = regmap_update_bits(rtc->rn5t618->regmap,
74                                  RN5T618_RTC_CTRL1, CTRL1_PERIODIC_MASK, 0);
75         if (err < 0)
76                 return err;
77
78         /* clear alarm flag and CTFG */
79         err = regmap_update_bits(rtc->rn5t618->regmap, RN5T618_RTC_CTRL2,
80                                  CTRL2_ALARM_STATUS | CTRL2_CTFG | CTRL2_CTC,
81                                  0);
82         if (err < 0)
83                 return err;
84
85         return 0;
86 }
87
88 /* things to be done once after power on */
89 static int rc5t619_rtc_pon_setup(struct device *dev)
90 {
91         struct rc5t619_rtc *rtc = dev_get_drvdata(dev);
92         int err;
93         unsigned int reg_data;
94
95         err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_CTRL2, &reg_data);
96         if (err < 0)
97                 return err;
98
99         /* clear VDET PON */
100         reg_data &= ~(CTRL2_PON | CTRL2_CTC | 0x4a);    /* 0101-1011 */
101         reg_data |= 0x20;       /* 0010-0000 */
102         err = regmap_write(rtc->rn5t618->regmap, RN5T618_RTC_CTRL2, reg_data);
103         if (err < 0)
104                 return err;
105
106         /* clearing RTC Adjust register */
107         err = regmap_write(rtc->rn5t618->regmap, RN5T618_RTC_ADJUST, 0);
108         if (err)
109                 return err;
110
111         return regmap_update_bits(rtc->rn5t618->regmap,
112                                         RN5T618_RTC_CTRL1,
113                                         CTRL1_24HR, CTRL1_24HR);
114 }
115
116 static int rc5t619_rtc_read_time(struct device *dev, struct rtc_time *tm)
117 {
118         struct rc5t619_rtc *rtc = dev_get_drvdata(dev);
119         u8 buff[7];
120         int err;
121         int cent_flag;
122         unsigned int ctrl1;
123         unsigned int ctrl2;
124
125         err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_CTRL2, &ctrl2);
126         if (err < 0)
127                 return err;
128
129         if (ctrl2 & CTRL2_PON)
130                 return -EINVAL;
131
132         err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_CTRL1, &ctrl1);
133         if (err < 0)
134                 return err;
135
136         err = regmap_bulk_read(rtc->rn5t618->regmap, RN5T618_RTC_SECONDS,
137                                buff, sizeof(buff));
138         if (err < 0)
139                 return err;
140
141         if (buff[5] & MONTH_CENTFLAG)
142                 cent_flag = 1;
143         else
144                 cent_flag = 0;
145
146         tm->tm_sec  = bcd2bin(buff[0]);
147         tm->tm_min  = bcd2bin(buff[1]);
148
149         if (ctrl1 & CTRL1_24HR)
150                 tm->tm_hour = bcd2bin(buff[2]);
151         else
152                 tm->tm_hour = rtc5t619_12hour_bcd2bin(buff[2]);
153
154         tm->tm_wday = bcd2bin(buff[3]);
155         tm->tm_mday = bcd2bin(buff[4]);
156         tm->tm_mon  = bcd2bin(buff[5] & 0x1f) - 1; /* back to system 0-11 */
157         tm->tm_year = bcd2bin(buff[6]) + 100 * cent_flag;
158
159         return 0;
160 }
161
162 static int rc5t619_rtc_set_time(struct device *dev, struct rtc_time *tm)
163 {
164         struct rc5t619_rtc *rtc = dev_get_drvdata(dev);
165         u8 buff[7];
166         int err;
167         int cent_flag;
168         unsigned int ctrl1;
169         unsigned int ctrl2;
170
171         err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_CTRL2, &ctrl2);
172         if (err < 0)
173                 return err;
174
175         if (ctrl2 & CTRL2_PON)
176                 rc5t619_rtc_pon_setup(dev);
177
178         err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_CTRL1, &ctrl1);
179         if (err < 0)
180                 return err;
181
182         if (tm->tm_year >= 100)
183                 cent_flag = 1;
184         else
185                 cent_flag = 0;
186
187         buff[0] = bin2bcd(tm->tm_sec);
188         buff[1] = bin2bcd(tm->tm_min);
189
190         if (ctrl1 & CTRL1_24HR)
191                 buff[2] = bin2bcd(tm->tm_hour);
192         else
193                 buff[2] = rtc5t619_12hour_bin2bcd(tm->tm_hour);
194
195         buff[3] = bin2bcd(tm->tm_wday);
196         buff[4] = bin2bcd(tm->tm_mday);
197         buff[5] = bin2bcd(tm->tm_mon + 1);      /* system set 0-11 */
198         buff[6] = bin2bcd(tm->tm_year - cent_flag * 100);
199
200         if (cent_flag)
201                 buff[5] |= MONTH_CENTFLAG;
202
203         err = regmap_bulk_write(rtc->rn5t618->regmap, RN5T618_RTC_SECONDS,
204                                 buff, sizeof(buff));
205         if (err < 0) {
206                 dev_err(dev, "failed to program new time: %d\n", err);
207                 return err;
208         }
209
210         return 0;
211 }
212
213 /* 0-disable, 1-enable */
214 static int rc5t619_rtc_alarm_enable(struct device *dev, unsigned int enabled)
215 {
216         struct rc5t619_rtc *rtc = dev_get_drvdata(dev);
217
218         return regmap_update_bits(rtc->rn5t618->regmap,
219                         RN5T618_RTC_CTRL1,
220                         CTRL1_ALARM_ENABLED,
221                         enabled ? CTRL1_ALARM_ENABLED : 0);
222 }
223
224 static int rc5t619_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
225 {
226         struct rc5t619_rtc *rtc = dev_get_drvdata(dev);
227         u8 buff[6];
228         unsigned int buff_cent;
229         int err;
230         int cent_flag;
231         unsigned int ctrl1;
232
233         err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_CTRL1, &ctrl1);
234         if (err)
235                 return err;
236
237         err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_MONTH, &buff_cent);
238         if (err < 0) {
239                 dev_err(dev, "failed to read time: %d\n", err);
240                 return err;
241         }
242
243         if (buff_cent & MONTH_CENTFLAG)
244                 cent_flag = 1;
245         else
246                 cent_flag = 0;
247
248         err = regmap_bulk_read(rtc->rn5t618->regmap, RN5T618_RTC_ALARM_Y_SEC,
249                                buff, sizeof(buff));
250         if (err)
251                 return err;
252
253         buff[3] = buff[3] & 0x3f;
254
255         alrm->time.tm_sec  = bcd2bin(buff[0]);
256         alrm->time.tm_min  = bcd2bin(buff[1]);
257
258         if (ctrl1 & CTRL1_24HR)
259                 alrm->time.tm_hour = bcd2bin(buff[2]);
260         else
261                 alrm->time.tm_hour = rtc5t619_12hour_bcd2bin(buff[2]);
262
263         alrm->time.tm_mday = bcd2bin(buff[3]);
264         alrm->time.tm_mon  = bcd2bin(buff[4]) - 1;
265         alrm->time.tm_year = bcd2bin(buff[5]) + 100 * cent_flag;
266         alrm->enabled = !!(ctrl1 & CTRL1_ALARM_ENABLED);
267         dev_dbg(dev, "read alarm: %ptR\n", &alrm->time);
268
269         return 0;
270 }
271
272 static int rc5t619_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
273 {
274         struct rc5t619_rtc *rtc = dev_get_drvdata(dev);
275         u8 buff[6];
276         int err;
277         int cent_flag;
278         unsigned int ctrl1;
279
280         err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_CTRL1, &ctrl1);
281         if (err)
282                 return err;
283
284         err = rc5t619_rtc_alarm_enable(dev, 0);
285         if (err < 0)
286                 return err;
287
288         if (rtc->irq == -1)
289                 return -EINVAL;
290
291         if (alrm->enabled == 0)
292                 return 0;
293
294         if (alrm->time.tm_year >= 100)
295                 cent_flag = 1;
296         else
297                 cent_flag = 0;
298
299         alrm->time.tm_mon += 1;
300         buff[0] = bin2bcd(alrm->time.tm_sec);
301         buff[1] = bin2bcd(alrm->time.tm_min);
302
303         if (ctrl1 & CTRL1_24HR)
304                 buff[2] = bin2bcd(alrm->time.tm_hour);
305         else
306                 buff[2] = rtc5t619_12hour_bin2bcd(alrm->time.tm_hour);
307
308         buff[3] = bin2bcd(alrm->time.tm_mday);
309         buff[4] = bin2bcd(alrm->time.tm_mon);
310         buff[5] = bin2bcd(alrm->time.tm_year - 100 * cent_flag);
311         buff[3] |= MDAY_DAL_EXT;
312
313         err = regmap_bulk_write(rtc->rn5t618->regmap, RN5T618_RTC_ALARM_Y_SEC,
314                                 buff, sizeof(buff));
315         if (err < 0)
316                 return err;
317
318         return rc5t619_rtc_alarm_enable(dev, alrm->enabled);
319 }
320
321 static const struct rtc_class_ops rc5t619_rtc_ops = {
322         .read_time      = rc5t619_rtc_read_time,
323         .set_time       = rc5t619_rtc_set_time,
324         .set_alarm      = rc5t619_rtc_set_alarm,
325         .read_alarm     = rc5t619_rtc_read_alarm,
326         .alarm_irq_enable = rc5t619_rtc_alarm_enable,
327 };
328
329 static int rc5t619_rtc_alarm_flag_clr(struct device *dev)
330 {
331         struct rc5t619_rtc *rtc = dev_get_drvdata(dev);
332
333         /* clear alarm-D status bits.*/
334         return regmap_update_bits(rtc->rn5t618->regmap,
335                                 RN5T618_RTC_CTRL2,
336                                 CTRL2_ALARM_STATUS | CTRL2_CTC, 0);
337 }
338
339 static irqreturn_t rc5t619_rtc_irq(int irq, void *data)
340 {
341         struct device *dev = data;
342         struct rc5t619_rtc *rtc = dev_get_drvdata(dev);
343
344         rc5t619_rtc_alarm_flag_clr(dev);
345
346         rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF);
347         return IRQ_HANDLED;
348 }
349
350 static int rc5t619_rtc_probe(struct platform_device *pdev)
351 {
352         struct device *dev = &pdev->dev;
353         struct rn5t618 *rn5t618 = dev_get_drvdata(pdev->dev.parent);
354         struct rc5t619_rtc *rtc;
355         unsigned int ctrl2;
356         int err;
357
358         rtc = devm_kzalloc(dev, sizeof(*rtc), GFP_KERNEL);
359         if (!rtc)
360                 return -ENOMEM;
361
362         rtc->rn5t618 = rn5t618;
363
364         dev_set_drvdata(dev, rtc);
365         rtc->irq = -1;
366
367         if (rn5t618->irq_data)
368                 rtc->irq = regmap_irq_get_virq(rn5t618->irq_data,
369                                                RN5T618_IRQ_RTC);
370
371         if (rtc->irq  < 0)
372                 rtc->irq = -1;
373
374         err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_CTRL2, &ctrl2);
375         if (err < 0)
376                 return err;
377
378         /* disable rtc periodic function */
379         err = rc5t619_rtc_periodic_disable(&pdev->dev);
380         if (err)
381                 return err;
382
383         if (ctrl2 & CTRL2_PON) {
384                 err = rc5t619_rtc_alarm_flag_clr(&pdev->dev);
385                 if (err)
386                         return err;
387         }
388
389         rtc->rtc = devm_rtc_allocate_device(&pdev->dev);
390         if (IS_ERR(rtc->rtc)) {
391                 err = PTR_ERR(rtc->rtc);
392                 dev_err(dev, "RTC device register: err %d\n", err);
393                 return err;
394         }
395
396         rtc->rtc->ops = &rc5t619_rtc_ops;
397         rtc->rtc->range_min = RTC_TIMESTAMP_BEGIN_1900;
398         rtc->rtc->range_max = RTC_TIMESTAMP_END_2099;
399
400         /* set interrupt and enable it */
401         if (rtc->irq != -1) {
402                 err = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL,
403                                                 rc5t619_rtc_irq,
404                                                 IRQF_ONESHOT,
405                                                 "rtc-rc5t619",
406                                                 &pdev->dev);
407                 if (err < 0) {
408                         dev_err(&pdev->dev, "request IRQ:%d fail\n", rtc->irq);
409                         rtc->irq = -1;
410
411                         err = rc5t619_rtc_alarm_enable(&pdev->dev, 0);
412                         if (err)
413                                 return err;
414
415                 } else {
416                         /* enable wake */
417                         device_init_wakeup(&pdev->dev, 1);
418                         enable_irq_wake(rtc->irq);
419                 }
420         } else {
421                 /* system don't want to using alarm interrupt, so close it */
422                 err = rc5t619_rtc_alarm_enable(&pdev->dev, 0);
423                 if (err)
424                         return err;
425
426                 dev_warn(&pdev->dev, "rc5t619 interrupt is disabled\n");
427         }
428
429         return rtc_register_device(rtc->rtc);
430 }
431
432 static struct platform_driver rc5t619_rtc_driver = {
433         .driver = {
434                 .name   = "rc5t619-rtc",
435         },
436         .probe  = rc5t619_rtc_probe,
437 };
438
439 module_platform_driver(rc5t619_rtc_driver);
440 MODULE_ALIAS("platform:rc5t619-rtc");
441 MODULE_DESCRIPTION("RICOH RC5T619 RTC driver");
442 MODULE_LICENSE("GPL");