4 * Joshua Henderson <joshua.henderson@microchip.com>
5 * Copyright (C) 2016 Microchip Technology Inc. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 #include <linux/init.h>
18 #include <linux/module.h>
20 #include <linux/platform_device.h>
22 #include <linux/slab.h>
23 #include <linux/clk.h>
24 #include <linux/rtc.h>
25 #include <linux/bcd.h>
27 #include <asm/mach-pic32/pic32.h>
29 #define PIC32_RTCCON 0x00
30 #define PIC32_RTCCON_ON BIT(15)
31 #define PIC32_RTCCON_SIDL BIT(13)
32 #define PIC32_RTCCON_RTCCLKSEL (3 << 9)
33 #define PIC32_RTCCON_RTCCLKON BIT(6)
34 #define PIC32_RTCCON_RTCWREN BIT(3)
35 #define PIC32_RTCCON_RTCSYNC BIT(2)
36 #define PIC32_RTCCON_HALFSEC BIT(1)
37 #define PIC32_RTCCON_RTCOE BIT(0)
39 #define PIC32_RTCALRM 0x10
40 #define PIC32_RTCALRM_ALRMEN BIT(15)
41 #define PIC32_RTCALRM_CHIME BIT(14)
42 #define PIC32_RTCALRM_PIV BIT(13)
43 #define PIC32_RTCALRM_ALARMSYNC BIT(12)
44 #define PIC32_RTCALRM_AMASK 0x0F00
45 #define PIC32_RTCALRM_ARPT 0xFF
47 #define PIC32_RTCHOUR 0x23
48 #define PIC32_RTCMIN 0x22
49 #define PIC32_RTCSEC 0x21
50 #define PIC32_RTCYEAR 0x33
51 #define PIC32_RTCMON 0x32
52 #define PIC32_RTCDAY 0x31
54 #define PIC32_ALRMTIME 0x40
55 #define PIC32_ALRMDATE 0x50
57 #define PIC32_ALRMHOUR 0x43
58 #define PIC32_ALRMMIN 0x42
59 #define PIC32_ALRMSEC 0x41
60 #define PIC32_ALRMYEAR 0x53
61 #define PIC32_ALRMMON 0x52
62 #define PIC32_ALRMDAY 0x51
64 struct pic32_rtc_dev
{
65 struct rtc_device
*rtc
;
66 void __iomem
*reg_base
;
68 spinlock_t alarm_lock
;
70 bool alarm_clk_enabled
;
73 static void pic32_rtc_alarm_clk_enable(struct pic32_rtc_dev
*pdata
,
78 spin_lock_irqsave(&pdata
->alarm_lock
, flags
);
80 if (!pdata
->alarm_clk_enabled
) {
81 clk_enable(pdata
->clk
);
82 pdata
->alarm_clk_enabled
= true;
85 if (pdata
->alarm_clk_enabled
) {
86 clk_disable(pdata
->clk
);
87 pdata
->alarm_clk_enabled
= false;
90 spin_unlock_irqrestore(&pdata
->alarm_lock
, flags
);
93 static irqreturn_t
pic32_rtc_alarmirq(int irq
, void *id
)
95 struct pic32_rtc_dev
*pdata
= (struct pic32_rtc_dev
*)id
;
97 clk_enable(pdata
->clk
);
98 rtc_update_irq(pdata
->rtc
, 1, RTC_AF
| RTC_IRQF
);
99 clk_disable(pdata
->clk
);
101 pic32_rtc_alarm_clk_enable(pdata
, false);
106 static int pic32_rtc_setaie(struct device
*dev
, unsigned int enabled
)
108 struct pic32_rtc_dev
*pdata
= dev_get_drvdata(dev
);
109 void __iomem
*base
= pdata
->reg_base
;
111 clk_enable(pdata
->clk
);
113 writel(PIC32_RTCALRM_ALRMEN
,
114 base
+ (enabled
? PIC32_SET(PIC32_RTCALRM
) :
115 PIC32_CLR(PIC32_RTCALRM
)));
117 clk_disable(pdata
->clk
);
119 pic32_rtc_alarm_clk_enable(pdata
, enabled
);
124 static int pic32_rtc_setfreq(struct device
*dev
, int freq
)
126 struct pic32_rtc_dev
*pdata
= dev_get_drvdata(dev
);
127 void __iomem
*base
= pdata
->reg_base
;
129 clk_enable(pdata
->clk
);
131 writel(PIC32_RTCALRM_AMASK
, base
+ PIC32_CLR(PIC32_RTCALRM
));
132 writel(freq
<< 8, base
+ PIC32_SET(PIC32_RTCALRM
));
133 writel(PIC32_RTCALRM_CHIME
, base
+ PIC32_SET(PIC32_RTCALRM
));
135 clk_disable(pdata
->clk
);
140 static int pic32_rtc_gettime(struct device
*dev
, struct rtc_time
*rtc_tm
)
142 struct pic32_rtc_dev
*pdata
= dev_get_drvdata(dev
);
143 void __iomem
*base
= pdata
->reg_base
;
144 unsigned int tries
= 0;
146 clk_enable(pdata
->clk
);
149 rtc_tm
->tm_hour
= readb(base
+ PIC32_RTCHOUR
);
150 rtc_tm
->tm_min
= readb(base
+ PIC32_RTCMIN
);
151 rtc_tm
->tm_mon
= readb(base
+ PIC32_RTCMON
);
152 rtc_tm
->tm_mday
= readb(base
+ PIC32_RTCDAY
);
153 rtc_tm
->tm_year
= readb(base
+ PIC32_RTCYEAR
);
154 rtc_tm
->tm_sec
= readb(base
+ PIC32_RTCSEC
);
157 * The only way to work out whether the system was mid-update
158 * when we read it is to check the second counter, and if it
159 * is zero, then we re-try the entire read.
162 } while (rtc_tm
->tm_sec
== 0 && tries
< 2);
164 rtc_tm
->tm_sec
= bcd2bin(rtc_tm
->tm_sec
);
165 rtc_tm
->tm_min
= bcd2bin(rtc_tm
->tm_min
);
166 rtc_tm
->tm_hour
= bcd2bin(rtc_tm
->tm_hour
);
167 rtc_tm
->tm_mday
= bcd2bin(rtc_tm
->tm_mday
);
168 rtc_tm
->tm_mon
= bcd2bin(rtc_tm
->tm_mon
) - 1;
169 rtc_tm
->tm_year
= bcd2bin(rtc_tm
->tm_year
);
171 rtc_tm
->tm_year
+= 100;
173 dev_dbg(dev
, "read time %04d.%02d.%02d %02d:%02d:%02d\n",
174 1900 + rtc_tm
->tm_year
, rtc_tm
->tm_mon
, rtc_tm
->tm_mday
,
175 rtc_tm
->tm_hour
, rtc_tm
->tm_min
, rtc_tm
->tm_sec
);
177 clk_disable(pdata
->clk
);
178 return rtc_valid_tm(rtc_tm
);
181 static int pic32_rtc_settime(struct device
*dev
, struct rtc_time
*tm
)
183 struct pic32_rtc_dev
*pdata
= dev_get_drvdata(dev
);
184 void __iomem
*base
= pdata
->reg_base
;
185 int year
= tm
->tm_year
- 100;
187 dev_dbg(dev
, "set time %04d.%02d.%02d %02d:%02d:%02d\n",
188 1900 + tm
->tm_year
, tm
->tm_mon
, tm
->tm_mday
,
189 tm
->tm_hour
, tm
->tm_min
, tm
->tm_sec
);
191 if (year
< 0 || year
>= 100) {
192 dev_err(dev
, "rtc only supports 100 years\n");
196 clk_enable(pdata
->clk
);
197 writeb(bin2bcd(tm
->tm_sec
), base
+ PIC32_RTCSEC
);
198 writeb(bin2bcd(tm
->tm_min
), base
+ PIC32_RTCMIN
);
199 writeb(bin2bcd(tm
->tm_hour
), base
+ PIC32_RTCHOUR
);
200 writeb(bin2bcd(tm
->tm_mday
), base
+ PIC32_RTCDAY
);
201 writeb(bin2bcd(tm
->tm_mon
+ 1), base
+ PIC32_RTCMON
);
202 writeb(bin2bcd(year
), base
+ PIC32_RTCYEAR
);
203 clk_disable(pdata
->clk
);
208 static int pic32_rtc_getalarm(struct device
*dev
, struct rtc_wkalrm
*alrm
)
210 struct pic32_rtc_dev
*pdata
= dev_get_drvdata(dev
);
211 struct rtc_time
*alm_tm
= &alrm
->time
;
212 void __iomem
*base
= pdata
->reg_base
;
215 clk_enable(pdata
->clk
);
216 alm_tm
->tm_sec
= readb(base
+ PIC32_ALRMSEC
);
217 alm_tm
->tm_min
= readb(base
+ PIC32_ALRMMIN
);
218 alm_tm
->tm_hour
= readb(base
+ PIC32_ALRMHOUR
);
219 alm_tm
->tm_mon
= readb(base
+ PIC32_ALRMMON
);
220 alm_tm
->tm_mday
= readb(base
+ PIC32_ALRMDAY
);
221 alm_tm
->tm_year
= readb(base
+ PIC32_ALRMYEAR
);
223 alm_en
= readb(base
+ PIC32_RTCALRM
);
225 alrm
->enabled
= (alm_en
& PIC32_RTCALRM_ALRMEN
) ? 1 : 0;
227 dev_dbg(dev
, "getalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n",
229 1900 + alm_tm
->tm_year
, alm_tm
->tm_mon
, alm_tm
->tm_mday
,
230 alm_tm
->tm_hour
, alm_tm
->tm_min
, alm_tm
->tm_sec
);
232 alm_tm
->tm_sec
= bcd2bin(alm_tm
->tm_sec
);
233 alm_tm
->tm_min
= bcd2bin(alm_tm
->tm_min
);
234 alm_tm
->tm_hour
= bcd2bin(alm_tm
->tm_hour
);
235 alm_tm
->tm_mday
= bcd2bin(alm_tm
->tm_mday
);
236 alm_tm
->tm_mon
= bcd2bin(alm_tm
->tm_mon
) - 1;
237 alm_tm
->tm_year
= bcd2bin(alm_tm
->tm_year
);
239 clk_disable(pdata
->clk
);
243 static int pic32_rtc_setalarm(struct device
*dev
, struct rtc_wkalrm
*alrm
)
245 struct pic32_rtc_dev
*pdata
= dev_get_drvdata(dev
);
246 struct rtc_time
*tm
= &alrm
->time
;
247 void __iomem
*base
= pdata
->reg_base
;
249 clk_enable(pdata
->clk
);
250 dev_dbg(dev
, "setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n",
252 1900 + tm
->tm_year
, tm
->tm_mon
+ 1, tm
->tm_mday
,
253 tm
->tm_hour
, tm
->tm_min
, tm
->tm_sec
);
255 writel(0x00, base
+ PIC32_ALRMTIME
);
256 writel(0x00, base
+ PIC32_ALRMDATE
);
258 pic32_rtc_setaie(dev
, alrm
->enabled
);
260 clk_disable(pdata
->clk
);
264 static int pic32_rtc_proc(struct device
*dev
, struct seq_file
*seq
)
266 struct pic32_rtc_dev
*pdata
= dev_get_drvdata(dev
);
267 void __iomem
*base
= pdata
->reg_base
;
270 clk_enable(pdata
->clk
);
272 repeat
= readw(base
+ PIC32_RTCALRM
);
273 repeat
&= PIC32_RTCALRM_ARPT
;
274 seq_printf(seq
, "periodic_IRQ\t: %s\n", repeat
? "yes" : "no");
276 clk_disable(pdata
->clk
);
280 static const struct rtc_class_ops pic32_rtcops
= {
281 .read_time
= pic32_rtc_gettime
,
282 .set_time
= pic32_rtc_settime
,
283 .read_alarm
= pic32_rtc_getalarm
,
284 .set_alarm
= pic32_rtc_setalarm
,
285 .proc
= pic32_rtc_proc
,
286 .alarm_irq_enable
= pic32_rtc_setaie
,
289 static void pic32_rtc_enable(struct pic32_rtc_dev
*pdata
, int en
)
291 void __iomem
*base
= pdata
->reg_base
;
296 clk_enable(pdata
->clk
);
298 writel(PIC32_RTCCON_ON
, base
+ PIC32_CLR(PIC32_RTCCON
));
300 pic32_syskey_unlock();
302 writel(PIC32_RTCCON_RTCWREN
, base
+ PIC32_SET(PIC32_RTCCON
));
303 writel(3 << 9, base
+ PIC32_CLR(PIC32_RTCCON
));
305 if (!(readl(base
+ PIC32_RTCCON
) & PIC32_RTCCON_ON
))
306 writel(PIC32_RTCCON_ON
, base
+ PIC32_SET(PIC32_RTCCON
));
308 clk_disable(pdata
->clk
);
311 static int pic32_rtc_remove(struct platform_device
*pdev
)
313 struct pic32_rtc_dev
*pdata
= platform_get_drvdata(pdev
);
315 pic32_rtc_setaie(&pdev
->dev
, 0);
316 clk_unprepare(pdata
->clk
);
322 static int pic32_rtc_probe(struct platform_device
*pdev
)
324 struct pic32_rtc_dev
*pdata
;
325 struct resource
*res
;
328 pdata
= devm_kzalloc(&pdev
->dev
, sizeof(*pdata
), GFP_KERNEL
);
332 platform_set_drvdata(pdev
, pdata
);
334 pdata
->alarm_irq
= platform_get_irq(pdev
, 0);
335 if (pdata
->alarm_irq
< 0) {
336 dev_err(&pdev
->dev
, "no irq for alarm\n");
337 return pdata
->alarm_irq
;
340 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
341 pdata
->reg_base
= devm_ioremap_resource(&pdev
->dev
, res
);
342 if (IS_ERR(pdata
->reg_base
))
343 return PTR_ERR(pdata
->reg_base
);
345 pdata
->clk
= devm_clk_get(&pdev
->dev
, NULL
);
346 if (IS_ERR(pdata
->clk
)) {
347 dev_err(&pdev
->dev
, "failed to find rtc clock source\n");
348 ret
= PTR_ERR(pdata
->clk
);
353 spin_lock_init(&pdata
->alarm_lock
);
355 clk_prepare_enable(pdata
->clk
);
357 pic32_rtc_enable(pdata
, 1);
359 device_init_wakeup(&pdev
->dev
, 1);
361 pdata
->rtc
= devm_rtc_device_register(&pdev
->dev
, pdev
->name
,
364 if (IS_ERR(pdata
->rtc
)) {
365 ret
= PTR_ERR(pdata
->rtc
);
369 pdata
->rtc
->max_user_freq
= 128;
371 pic32_rtc_setfreq(&pdev
->dev
, 1);
372 ret
= devm_request_irq(&pdev
->dev
, pdata
->alarm_irq
,
373 pic32_rtc_alarmirq
, 0,
374 dev_name(&pdev
->dev
), pdata
);
377 "IRQ %d error %d\n", pdata
->alarm_irq
, ret
);
381 clk_disable(pdata
->clk
);
386 pic32_rtc_enable(pdata
, 0);
387 clk_disable_unprepare(pdata
->clk
);
392 static const struct of_device_id pic32_rtc_dt_ids
[] = {
393 { .compatible
= "microchip,pic32mzda-rtc" },
396 MODULE_DEVICE_TABLE(of
, pic32_rtc_dt_ids
);
398 static struct platform_driver pic32_rtc_driver
= {
399 .probe
= pic32_rtc_probe
,
400 .remove
= pic32_rtc_remove
,
403 .of_match_table
= of_match_ptr(pic32_rtc_dt_ids
),
406 module_platform_driver(pic32_rtc_driver
);
408 MODULE_DESCRIPTION("Microchip PIC32 RTC Driver");
409 MODULE_AUTHOR("Joshua Henderson <joshua.henderson@microchip.com>");
410 MODULE_LICENSE("GPL");