1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Driver for NEC VR4100 series Real Time Clock unit.
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2003-2008 Yoichi Yuasa <yuasa@linux-mips.org>
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun #include <linux/compat.h>
8*4882a593Smuzhiyun #include <linux/err.h>
9*4882a593Smuzhiyun #include <linux/fs.h>
10*4882a593Smuzhiyun #include <linux/init.h>
11*4882a593Smuzhiyun #include <linux/io.h>
12*4882a593Smuzhiyun #include <linux/ioport.h>
13*4882a593Smuzhiyun #include <linux/interrupt.h>
14*4882a593Smuzhiyun #include <linux/module.h>
15*4882a593Smuzhiyun #include <linux/platform_device.h>
16*4882a593Smuzhiyun #include <linux/rtc.h>
17*4882a593Smuzhiyun #include <linux/spinlock.h>
18*4882a593Smuzhiyun #include <linux/types.h>
19*4882a593Smuzhiyun #include <linux/uaccess.h>
20*4882a593Smuzhiyun #include <linux/log2.h>
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun #include <asm/div64.h>
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>");
25*4882a593Smuzhiyun MODULE_DESCRIPTION("NEC VR4100 series RTC driver");
26*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun /* RTC 1 registers */
29*4882a593Smuzhiyun #define ETIMELREG 0x00
30*4882a593Smuzhiyun #define ETIMEMREG 0x02
31*4882a593Smuzhiyun #define ETIMEHREG 0x04
32*4882a593Smuzhiyun /* RFU */
33*4882a593Smuzhiyun #define ECMPLREG 0x08
34*4882a593Smuzhiyun #define ECMPMREG 0x0a
35*4882a593Smuzhiyun #define ECMPHREG 0x0c
36*4882a593Smuzhiyun /* RFU */
37*4882a593Smuzhiyun #define RTCL1LREG 0x10
38*4882a593Smuzhiyun #define RTCL1HREG 0x12
39*4882a593Smuzhiyun #define RTCL1CNTLREG 0x14
40*4882a593Smuzhiyun #define RTCL1CNTHREG 0x16
41*4882a593Smuzhiyun #define RTCL2LREG 0x18
42*4882a593Smuzhiyun #define RTCL2HREG 0x1a
43*4882a593Smuzhiyun #define RTCL2CNTLREG 0x1c
44*4882a593Smuzhiyun #define RTCL2CNTHREG 0x1e
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun /* RTC 2 registers */
47*4882a593Smuzhiyun #define TCLKLREG 0x00
48*4882a593Smuzhiyun #define TCLKHREG 0x02
49*4882a593Smuzhiyun #define TCLKCNTLREG 0x04
50*4882a593Smuzhiyun #define TCLKCNTHREG 0x06
51*4882a593Smuzhiyun /* RFU */
52*4882a593Smuzhiyun #define RTCINTREG 0x1e
53*4882a593Smuzhiyun #define TCLOCK_INT 0x08
54*4882a593Smuzhiyun #define RTCLONG2_INT 0x04
55*4882a593Smuzhiyun #define RTCLONG1_INT 0x02
56*4882a593Smuzhiyun #define ELAPSEDTIME_INT 0x01
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun #define RTC_FREQUENCY 32768
59*4882a593Smuzhiyun #define MAX_PERIODIC_RATE 6553
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun static void __iomem *rtc1_base;
62*4882a593Smuzhiyun static void __iomem *rtc2_base;
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun #define rtc1_read(offset) readw(rtc1_base + (offset))
65*4882a593Smuzhiyun #define rtc1_write(offset, value) writew((value), rtc1_base + (offset))
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun #define rtc2_read(offset) readw(rtc2_base + (offset))
68*4882a593Smuzhiyun #define rtc2_write(offset, value) writew((value), rtc2_base + (offset))
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun /* 32-bit compat for ioctls that nobody else uses */
71*4882a593Smuzhiyun #define RTC_EPOCH_READ32 _IOR('p', 0x0d, __u32)
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun static unsigned long epoch = 1970; /* Jan 1 1970 00:00:00 */
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun static DEFINE_SPINLOCK(rtc_lock);
76*4882a593Smuzhiyun static char rtc_name[] = "RTC";
77*4882a593Smuzhiyun static unsigned long periodic_count;
78*4882a593Smuzhiyun static unsigned int alarm_enabled;
79*4882a593Smuzhiyun static int aie_irq;
80*4882a593Smuzhiyun static int pie_irq;
81*4882a593Smuzhiyun
read_elapsed_second(void)82*4882a593Smuzhiyun static inline time64_t read_elapsed_second(void)
83*4882a593Smuzhiyun {
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun unsigned long first_low, first_mid, first_high;
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun unsigned long second_low, second_mid, second_high;
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun do {
90*4882a593Smuzhiyun first_low = rtc1_read(ETIMELREG);
91*4882a593Smuzhiyun first_mid = rtc1_read(ETIMEMREG);
92*4882a593Smuzhiyun first_high = rtc1_read(ETIMEHREG);
93*4882a593Smuzhiyun second_low = rtc1_read(ETIMELREG);
94*4882a593Smuzhiyun second_mid = rtc1_read(ETIMEMREG);
95*4882a593Smuzhiyun second_high = rtc1_read(ETIMEHREG);
96*4882a593Smuzhiyun } while (first_low != second_low || first_mid != second_mid ||
97*4882a593Smuzhiyun first_high != second_high);
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun return ((u64)first_high << 17) | (first_mid << 1) | (first_low >> 15);
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun
write_elapsed_second(time64_t sec)102*4882a593Smuzhiyun static inline void write_elapsed_second(time64_t sec)
103*4882a593Smuzhiyun {
104*4882a593Smuzhiyun spin_lock_irq(&rtc_lock);
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun rtc1_write(ETIMELREG, (uint16_t)(sec << 15));
107*4882a593Smuzhiyun rtc1_write(ETIMEMREG, (uint16_t)(sec >> 1));
108*4882a593Smuzhiyun rtc1_write(ETIMEHREG, (uint16_t)(sec >> 17));
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun spin_unlock_irq(&rtc_lock);
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun
vr41xx_rtc_read_time(struct device * dev,struct rtc_time * time)113*4882a593Smuzhiyun static int vr41xx_rtc_read_time(struct device *dev, struct rtc_time *time)
114*4882a593Smuzhiyun {
115*4882a593Smuzhiyun time64_t epoch_sec, elapsed_sec;
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun epoch_sec = mktime64(epoch, 1, 1, 0, 0, 0);
118*4882a593Smuzhiyun elapsed_sec = read_elapsed_second();
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun rtc_time64_to_tm(epoch_sec + elapsed_sec, time);
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun return 0;
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun
vr41xx_rtc_set_time(struct device * dev,struct rtc_time * time)125*4882a593Smuzhiyun static int vr41xx_rtc_set_time(struct device *dev, struct rtc_time *time)
126*4882a593Smuzhiyun {
127*4882a593Smuzhiyun time64_t epoch_sec, current_sec;
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun epoch_sec = mktime64(epoch, 1, 1, 0, 0, 0);
130*4882a593Smuzhiyun current_sec = rtc_tm_to_time64(time);
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun write_elapsed_second(current_sec - epoch_sec);
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun return 0;
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun
vr41xx_rtc_read_alarm(struct device * dev,struct rtc_wkalrm * wkalrm)137*4882a593Smuzhiyun static int vr41xx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
138*4882a593Smuzhiyun {
139*4882a593Smuzhiyun unsigned long low, mid, high;
140*4882a593Smuzhiyun struct rtc_time *time = &wkalrm->time;
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun spin_lock_irq(&rtc_lock);
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun low = rtc1_read(ECMPLREG);
145*4882a593Smuzhiyun mid = rtc1_read(ECMPMREG);
146*4882a593Smuzhiyun high = rtc1_read(ECMPHREG);
147*4882a593Smuzhiyun wkalrm->enabled = alarm_enabled;
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun spin_unlock_irq(&rtc_lock);
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun rtc_time64_to_tm((high << 17) | (mid << 1) | (low >> 15), time);
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun return 0;
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun
vr41xx_rtc_set_alarm(struct device * dev,struct rtc_wkalrm * wkalrm)156*4882a593Smuzhiyun static int vr41xx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
157*4882a593Smuzhiyun {
158*4882a593Smuzhiyun time64_t alarm_sec;
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun alarm_sec = rtc_tm_to_time64(&wkalrm->time);
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun spin_lock_irq(&rtc_lock);
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun if (alarm_enabled)
165*4882a593Smuzhiyun disable_irq(aie_irq);
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun rtc1_write(ECMPLREG, (uint16_t)(alarm_sec << 15));
168*4882a593Smuzhiyun rtc1_write(ECMPMREG, (uint16_t)(alarm_sec >> 1));
169*4882a593Smuzhiyun rtc1_write(ECMPHREG, (uint16_t)(alarm_sec >> 17));
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun if (wkalrm->enabled)
172*4882a593Smuzhiyun enable_irq(aie_irq);
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun alarm_enabled = wkalrm->enabled;
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun spin_unlock_irq(&rtc_lock);
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun return 0;
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun
vr41xx_rtc_ioctl(struct device * dev,unsigned int cmd,unsigned long arg)181*4882a593Smuzhiyun static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
182*4882a593Smuzhiyun {
183*4882a593Smuzhiyun switch (cmd) {
184*4882a593Smuzhiyun case RTC_EPOCH_READ:
185*4882a593Smuzhiyun return put_user(epoch, (unsigned long __user *)arg);
186*4882a593Smuzhiyun #ifdef CONFIG_64BIT
187*4882a593Smuzhiyun case RTC_EPOCH_READ32:
188*4882a593Smuzhiyun return put_user(epoch, (unsigned int __user *)arg);
189*4882a593Smuzhiyun #endif
190*4882a593Smuzhiyun case RTC_EPOCH_SET:
191*4882a593Smuzhiyun /* Doesn't support before 1900 */
192*4882a593Smuzhiyun if (arg < 1900)
193*4882a593Smuzhiyun return -EINVAL;
194*4882a593Smuzhiyun epoch = arg;
195*4882a593Smuzhiyun break;
196*4882a593Smuzhiyun default:
197*4882a593Smuzhiyun return -ENOIOCTLCMD;
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun return 0;
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun
vr41xx_rtc_alarm_irq_enable(struct device * dev,unsigned int enabled)203*4882a593Smuzhiyun static int vr41xx_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
204*4882a593Smuzhiyun {
205*4882a593Smuzhiyun spin_lock_irq(&rtc_lock);
206*4882a593Smuzhiyun if (enabled) {
207*4882a593Smuzhiyun if (!alarm_enabled) {
208*4882a593Smuzhiyun enable_irq(aie_irq);
209*4882a593Smuzhiyun alarm_enabled = 1;
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun } else {
212*4882a593Smuzhiyun if (alarm_enabled) {
213*4882a593Smuzhiyun disable_irq(aie_irq);
214*4882a593Smuzhiyun alarm_enabled = 0;
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun spin_unlock_irq(&rtc_lock);
218*4882a593Smuzhiyun return 0;
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun
elapsedtime_interrupt(int irq,void * dev_id)221*4882a593Smuzhiyun static irqreturn_t elapsedtime_interrupt(int irq, void *dev_id)
222*4882a593Smuzhiyun {
223*4882a593Smuzhiyun struct platform_device *pdev = (struct platform_device *)dev_id;
224*4882a593Smuzhiyun struct rtc_device *rtc = platform_get_drvdata(pdev);
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun rtc2_write(RTCINTREG, ELAPSEDTIME_INT);
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun rtc_update_irq(rtc, 1, RTC_AF);
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun return IRQ_HANDLED;
231*4882a593Smuzhiyun }
232*4882a593Smuzhiyun
rtclong1_interrupt(int irq,void * dev_id)233*4882a593Smuzhiyun static irqreturn_t rtclong1_interrupt(int irq, void *dev_id)
234*4882a593Smuzhiyun {
235*4882a593Smuzhiyun struct platform_device *pdev = (struct platform_device *)dev_id;
236*4882a593Smuzhiyun struct rtc_device *rtc = platform_get_drvdata(pdev);
237*4882a593Smuzhiyun unsigned long count = periodic_count;
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun rtc2_write(RTCINTREG, RTCLONG1_INT);
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun rtc1_write(RTCL1LREG, count);
242*4882a593Smuzhiyun rtc1_write(RTCL1HREG, count >> 16);
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun rtc_update_irq(rtc, 1, RTC_PF);
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun return IRQ_HANDLED;
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun static const struct rtc_class_ops vr41xx_rtc_ops = {
250*4882a593Smuzhiyun .ioctl = vr41xx_rtc_ioctl,
251*4882a593Smuzhiyun .read_time = vr41xx_rtc_read_time,
252*4882a593Smuzhiyun .set_time = vr41xx_rtc_set_time,
253*4882a593Smuzhiyun .read_alarm = vr41xx_rtc_read_alarm,
254*4882a593Smuzhiyun .set_alarm = vr41xx_rtc_set_alarm,
255*4882a593Smuzhiyun .alarm_irq_enable = vr41xx_rtc_alarm_irq_enable,
256*4882a593Smuzhiyun };
257*4882a593Smuzhiyun
rtc_probe(struct platform_device * pdev)258*4882a593Smuzhiyun static int rtc_probe(struct platform_device *pdev)
259*4882a593Smuzhiyun {
260*4882a593Smuzhiyun struct resource *res;
261*4882a593Smuzhiyun struct rtc_device *rtc;
262*4882a593Smuzhiyun int retval;
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun if (pdev->num_resources != 4)
265*4882a593Smuzhiyun return -EBUSY;
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
268*4882a593Smuzhiyun if (!res)
269*4882a593Smuzhiyun return -EBUSY;
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun rtc1_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
272*4882a593Smuzhiyun if (!rtc1_base)
273*4882a593Smuzhiyun return -EBUSY;
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
276*4882a593Smuzhiyun if (!res) {
277*4882a593Smuzhiyun retval = -EBUSY;
278*4882a593Smuzhiyun goto err_rtc1_iounmap;
279*4882a593Smuzhiyun }
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun rtc2_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
282*4882a593Smuzhiyun if (!rtc2_base) {
283*4882a593Smuzhiyun retval = -EBUSY;
284*4882a593Smuzhiyun goto err_rtc1_iounmap;
285*4882a593Smuzhiyun }
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun rtc = devm_rtc_allocate_device(&pdev->dev);
288*4882a593Smuzhiyun if (IS_ERR(rtc)) {
289*4882a593Smuzhiyun retval = PTR_ERR(rtc);
290*4882a593Smuzhiyun goto err_iounmap_all;
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun rtc->ops = &vr41xx_rtc_ops;
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun /* 48-bit counter at 32.768 kHz */
296*4882a593Smuzhiyun rtc->range_max = (1ULL << 33) - 1;
297*4882a593Smuzhiyun rtc->max_user_freq = MAX_PERIODIC_RATE;
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun spin_lock_irq(&rtc_lock);
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun rtc1_write(ECMPLREG, 0);
302*4882a593Smuzhiyun rtc1_write(ECMPMREG, 0);
303*4882a593Smuzhiyun rtc1_write(ECMPHREG, 0);
304*4882a593Smuzhiyun rtc1_write(RTCL1LREG, 0);
305*4882a593Smuzhiyun rtc1_write(RTCL1HREG, 0);
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun spin_unlock_irq(&rtc_lock);
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun aie_irq = platform_get_irq(pdev, 0);
310*4882a593Smuzhiyun if (aie_irq <= 0) {
311*4882a593Smuzhiyun retval = -EBUSY;
312*4882a593Smuzhiyun goto err_iounmap_all;
313*4882a593Smuzhiyun }
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun retval = devm_request_irq(&pdev->dev, aie_irq, elapsedtime_interrupt, 0,
316*4882a593Smuzhiyun "elapsed_time", pdev);
317*4882a593Smuzhiyun if (retval < 0)
318*4882a593Smuzhiyun goto err_iounmap_all;
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun pie_irq = platform_get_irq(pdev, 1);
321*4882a593Smuzhiyun if (pie_irq <= 0) {
322*4882a593Smuzhiyun retval = -EBUSY;
323*4882a593Smuzhiyun goto err_iounmap_all;
324*4882a593Smuzhiyun }
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun retval = devm_request_irq(&pdev->dev, pie_irq, rtclong1_interrupt, 0,
327*4882a593Smuzhiyun "rtclong1", pdev);
328*4882a593Smuzhiyun if (retval < 0)
329*4882a593Smuzhiyun goto err_iounmap_all;
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun platform_set_drvdata(pdev, rtc);
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun disable_irq(aie_irq);
334*4882a593Smuzhiyun disable_irq(pie_irq);
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun dev_info(&pdev->dev, "Real Time Clock of NEC VR4100 series\n");
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun retval = rtc_register_device(rtc);
339*4882a593Smuzhiyun if (retval)
340*4882a593Smuzhiyun goto err_iounmap_all;
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun return 0;
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun err_iounmap_all:
345*4882a593Smuzhiyun rtc2_base = NULL;
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun err_rtc1_iounmap:
348*4882a593Smuzhiyun rtc1_base = NULL;
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun return retval;
351*4882a593Smuzhiyun }
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun /* work with hotplug and coldplug */
354*4882a593Smuzhiyun MODULE_ALIAS("platform:RTC");
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun static struct platform_driver rtc_platform_driver = {
357*4882a593Smuzhiyun .probe = rtc_probe,
358*4882a593Smuzhiyun .driver = {
359*4882a593Smuzhiyun .name = rtc_name,
360*4882a593Smuzhiyun },
361*4882a593Smuzhiyun };
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun module_platform_driver(rtc_platform_driver);
364