1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * TX4939 internal RTC driver
4*4882a593Smuzhiyun * Based on RBTX49xx patch from CELF patch archive.
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * (C) Copyright TOSHIBA CORPORATION 2005-2007
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun #include <linux/rtc.h>
9*4882a593Smuzhiyun #include <linux/platform_device.h>
10*4882a593Smuzhiyun #include <linux/interrupt.h>
11*4882a593Smuzhiyun #include <linux/module.h>
12*4882a593Smuzhiyun #include <linux/io.h>
13*4882a593Smuzhiyun #include <linux/gfp.h>
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun #define TX4939_RTCCTL_ALME 0x00000080
16*4882a593Smuzhiyun #define TX4939_RTCCTL_ALMD 0x00000040
17*4882a593Smuzhiyun #define TX4939_RTCCTL_BUSY 0x00000020
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #define TX4939_RTCCTL_COMMAND 0x00000007
20*4882a593Smuzhiyun #define TX4939_RTCCTL_COMMAND_NOP 0x00000000
21*4882a593Smuzhiyun #define TX4939_RTCCTL_COMMAND_GETTIME 0x00000001
22*4882a593Smuzhiyun #define TX4939_RTCCTL_COMMAND_SETTIME 0x00000002
23*4882a593Smuzhiyun #define TX4939_RTCCTL_COMMAND_GETALARM 0x00000003
24*4882a593Smuzhiyun #define TX4939_RTCCTL_COMMAND_SETALARM 0x00000004
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun #define TX4939_RTCTBC_PM 0x00000080
27*4882a593Smuzhiyun #define TX4939_RTCTBC_COMP 0x0000007f
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun #define TX4939_RTC_REG_RAMSIZE 0x00000100
30*4882a593Smuzhiyun #define TX4939_RTC_REG_RWBSIZE 0x00000006
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun struct tx4939_rtc_reg {
33*4882a593Smuzhiyun __u32 ctl;
34*4882a593Smuzhiyun __u32 adr;
35*4882a593Smuzhiyun __u32 dat;
36*4882a593Smuzhiyun __u32 tbc;
37*4882a593Smuzhiyun };
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun struct tx4939rtc_plat_data {
40*4882a593Smuzhiyun struct rtc_device *rtc;
41*4882a593Smuzhiyun struct tx4939_rtc_reg __iomem *rtcreg;
42*4882a593Smuzhiyun spinlock_t lock;
43*4882a593Smuzhiyun };
44*4882a593Smuzhiyun
tx4939_rtc_cmd(struct tx4939_rtc_reg __iomem * rtcreg,int cmd)45*4882a593Smuzhiyun static int tx4939_rtc_cmd(struct tx4939_rtc_reg __iomem *rtcreg, int cmd)
46*4882a593Smuzhiyun {
47*4882a593Smuzhiyun int i = 0;
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun __raw_writel(cmd, &rtcreg->ctl);
50*4882a593Smuzhiyun /* This might take 30us (next 32.768KHz clock) */
51*4882a593Smuzhiyun while (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_BUSY) {
52*4882a593Smuzhiyun /* timeout on approx. 100us (@ GBUS200MHz) */
53*4882a593Smuzhiyun if (i++ > 200 * 100)
54*4882a593Smuzhiyun return -EBUSY;
55*4882a593Smuzhiyun cpu_relax();
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun return 0;
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun
tx4939_rtc_set_time(struct device * dev,struct rtc_time * tm)60*4882a593Smuzhiyun static int tx4939_rtc_set_time(struct device *dev, struct rtc_time *tm)
61*4882a593Smuzhiyun {
62*4882a593Smuzhiyun struct tx4939rtc_plat_data *pdata = dev_get_drvdata(dev);
63*4882a593Smuzhiyun struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg;
64*4882a593Smuzhiyun unsigned long secs = rtc_tm_to_time64(tm);
65*4882a593Smuzhiyun int i, ret;
66*4882a593Smuzhiyun unsigned char buf[6];
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun buf[0] = 0;
69*4882a593Smuzhiyun buf[1] = 0;
70*4882a593Smuzhiyun buf[2] = secs;
71*4882a593Smuzhiyun buf[3] = secs >> 8;
72*4882a593Smuzhiyun buf[4] = secs >> 16;
73*4882a593Smuzhiyun buf[5] = secs >> 24;
74*4882a593Smuzhiyun spin_lock_irq(&pdata->lock);
75*4882a593Smuzhiyun __raw_writel(0, &rtcreg->adr);
76*4882a593Smuzhiyun for (i = 0; i < 6; i++)
77*4882a593Smuzhiyun __raw_writel(buf[i], &rtcreg->dat);
78*4882a593Smuzhiyun ret = tx4939_rtc_cmd(rtcreg,
79*4882a593Smuzhiyun TX4939_RTCCTL_COMMAND_SETTIME |
80*4882a593Smuzhiyun (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME));
81*4882a593Smuzhiyun spin_unlock_irq(&pdata->lock);
82*4882a593Smuzhiyun return ret;
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun
tx4939_rtc_read_time(struct device * dev,struct rtc_time * tm)85*4882a593Smuzhiyun static int tx4939_rtc_read_time(struct device *dev, struct rtc_time *tm)
86*4882a593Smuzhiyun {
87*4882a593Smuzhiyun struct tx4939rtc_plat_data *pdata = dev_get_drvdata(dev);
88*4882a593Smuzhiyun struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg;
89*4882a593Smuzhiyun int i, ret;
90*4882a593Smuzhiyun unsigned long sec;
91*4882a593Smuzhiyun unsigned char buf[6];
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun spin_lock_irq(&pdata->lock);
94*4882a593Smuzhiyun ret = tx4939_rtc_cmd(rtcreg,
95*4882a593Smuzhiyun TX4939_RTCCTL_COMMAND_GETTIME |
96*4882a593Smuzhiyun (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME));
97*4882a593Smuzhiyun if (ret) {
98*4882a593Smuzhiyun spin_unlock_irq(&pdata->lock);
99*4882a593Smuzhiyun return ret;
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun __raw_writel(2, &rtcreg->adr);
102*4882a593Smuzhiyun for (i = 2; i < 6; i++)
103*4882a593Smuzhiyun buf[i] = __raw_readl(&rtcreg->dat);
104*4882a593Smuzhiyun spin_unlock_irq(&pdata->lock);
105*4882a593Smuzhiyun sec = ((unsigned long)buf[5] << 24) | (buf[4] << 16) |
106*4882a593Smuzhiyun (buf[3] << 8) | buf[2];
107*4882a593Smuzhiyun rtc_time64_to_tm(sec, tm);
108*4882a593Smuzhiyun return 0;
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun
tx4939_rtc_set_alarm(struct device * dev,struct rtc_wkalrm * alrm)111*4882a593Smuzhiyun static int tx4939_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
112*4882a593Smuzhiyun {
113*4882a593Smuzhiyun struct tx4939rtc_plat_data *pdata = dev_get_drvdata(dev);
114*4882a593Smuzhiyun struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg;
115*4882a593Smuzhiyun int i, ret;
116*4882a593Smuzhiyun unsigned long sec;
117*4882a593Smuzhiyun unsigned char buf[6];
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun sec = rtc_tm_to_time64(&alrm->time);
120*4882a593Smuzhiyun buf[0] = 0;
121*4882a593Smuzhiyun buf[1] = 0;
122*4882a593Smuzhiyun buf[2] = sec;
123*4882a593Smuzhiyun buf[3] = sec >> 8;
124*4882a593Smuzhiyun buf[4] = sec >> 16;
125*4882a593Smuzhiyun buf[5] = sec >> 24;
126*4882a593Smuzhiyun spin_lock_irq(&pdata->lock);
127*4882a593Smuzhiyun __raw_writel(0, &rtcreg->adr);
128*4882a593Smuzhiyun for (i = 0; i < 6; i++)
129*4882a593Smuzhiyun __raw_writel(buf[i], &rtcreg->dat);
130*4882a593Smuzhiyun ret = tx4939_rtc_cmd(rtcreg, TX4939_RTCCTL_COMMAND_SETALARM |
131*4882a593Smuzhiyun (alrm->enabled ? TX4939_RTCCTL_ALME : 0));
132*4882a593Smuzhiyun spin_unlock_irq(&pdata->lock);
133*4882a593Smuzhiyun return ret;
134*4882a593Smuzhiyun }
135*4882a593Smuzhiyun
tx4939_rtc_read_alarm(struct device * dev,struct rtc_wkalrm * alrm)136*4882a593Smuzhiyun static int tx4939_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
137*4882a593Smuzhiyun {
138*4882a593Smuzhiyun struct tx4939rtc_plat_data *pdata = dev_get_drvdata(dev);
139*4882a593Smuzhiyun struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg;
140*4882a593Smuzhiyun int i, ret;
141*4882a593Smuzhiyun unsigned long sec;
142*4882a593Smuzhiyun unsigned char buf[6];
143*4882a593Smuzhiyun u32 ctl;
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun spin_lock_irq(&pdata->lock);
146*4882a593Smuzhiyun ret = tx4939_rtc_cmd(rtcreg,
147*4882a593Smuzhiyun TX4939_RTCCTL_COMMAND_GETALARM |
148*4882a593Smuzhiyun (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME));
149*4882a593Smuzhiyun if (ret) {
150*4882a593Smuzhiyun spin_unlock_irq(&pdata->lock);
151*4882a593Smuzhiyun return ret;
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun __raw_writel(2, &rtcreg->adr);
154*4882a593Smuzhiyun for (i = 2; i < 6; i++)
155*4882a593Smuzhiyun buf[i] = __raw_readl(&rtcreg->dat);
156*4882a593Smuzhiyun ctl = __raw_readl(&rtcreg->ctl);
157*4882a593Smuzhiyun alrm->enabled = (ctl & TX4939_RTCCTL_ALME) ? 1 : 0;
158*4882a593Smuzhiyun alrm->pending = (ctl & TX4939_RTCCTL_ALMD) ? 1 : 0;
159*4882a593Smuzhiyun spin_unlock_irq(&pdata->lock);
160*4882a593Smuzhiyun sec = ((unsigned long)buf[5] << 24) | (buf[4] << 16) |
161*4882a593Smuzhiyun (buf[3] << 8) | buf[2];
162*4882a593Smuzhiyun rtc_time64_to_tm(sec, &alrm->time);
163*4882a593Smuzhiyun return rtc_valid_tm(&alrm->time);
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun
tx4939_rtc_alarm_irq_enable(struct device * dev,unsigned int enabled)166*4882a593Smuzhiyun static int tx4939_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
167*4882a593Smuzhiyun {
168*4882a593Smuzhiyun struct tx4939rtc_plat_data *pdata = dev_get_drvdata(dev);
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun spin_lock_irq(&pdata->lock);
171*4882a593Smuzhiyun tx4939_rtc_cmd(pdata->rtcreg,
172*4882a593Smuzhiyun TX4939_RTCCTL_COMMAND_NOP |
173*4882a593Smuzhiyun (enabled ? TX4939_RTCCTL_ALME : 0));
174*4882a593Smuzhiyun spin_unlock_irq(&pdata->lock);
175*4882a593Smuzhiyun return 0;
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun
tx4939_rtc_interrupt(int irq,void * dev_id)178*4882a593Smuzhiyun static irqreturn_t tx4939_rtc_interrupt(int irq, void *dev_id)
179*4882a593Smuzhiyun {
180*4882a593Smuzhiyun struct tx4939rtc_plat_data *pdata = dev_get_drvdata(dev_id);
181*4882a593Smuzhiyun struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg;
182*4882a593Smuzhiyun unsigned long events = RTC_IRQF;
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun spin_lock(&pdata->lock);
185*4882a593Smuzhiyun if (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALMD) {
186*4882a593Smuzhiyun events |= RTC_AF;
187*4882a593Smuzhiyun tx4939_rtc_cmd(rtcreg, TX4939_RTCCTL_COMMAND_NOP);
188*4882a593Smuzhiyun }
189*4882a593Smuzhiyun spin_unlock(&pdata->lock);
190*4882a593Smuzhiyun rtc_update_irq(pdata->rtc, 1, events);
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun return IRQ_HANDLED;
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun static const struct rtc_class_ops tx4939_rtc_ops = {
196*4882a593Smuzhiyun .read_time = tx4939_rtc_read_time,
197*4882a593Smuzhiyun .read_alarm = tx4939_rtc_read_alarm,
198*4882a593Smuzhiyun .set_alarm = tx4939_rtc_set_alarm,
199*4882a593Smuzhiyun .set_time = tx4939_rtc_set_time,
200*4882a593Smuzhiyun .alarm_irq_enable = tx4939_rtc_alarm_irq_enable,
201*4882a593Smuzhiyun };
202*4882a593Smuzhiyun
tx4939_nvram_read(void * priv,unsigned int pos,void * val,size_t bytes)203*4882a593Smuzhiyun static int tx4939_nvram_read(void *priv, unsigned int pos, void *val,
204*4882a593Smuzhiyun size_t bytes)
205*4882a593Smuzhiyun {
206*4882a593Smuzhiyun struct tx4939rtc_plat_data *pdata = priv;
207*4882a593Smuzhiyun struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg;
208*4882a593Smuzhiyun u8 *buf = val;
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun spin_lock_irq(&pdata->lock);
211*4882a593Smuzhiyun for (; bytes; bytes--) {
212*4882a593Smuzhiyun __raw_writel(pos++, &rtcreg->adr);
213*4882a593Smuzhiyun *buf++ = __raw_readl(&rtcreg->dat);
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun spin_unlock_irq(&pdata->lock);
216*4882a593Smuzhiyun return 0;
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun
tx4939_nvram_write(void * priv,unsigned int pos,void * val,size_t bytes)219*4882a593Smuzhiyun static int tx4939_nvram_write(void *priv, unsigned int pos, void *val,
220*4882a593Smuzhiyun size_t bytes)
221*4882a593Smuzhiyun {
222*4882a593Smuzhiyun struct tx4939rtc_plat_data *pdata = priv;
223*4882a593Smuzhiyun struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg;
224*4882a593Smuzhiyun u8 *buf = val;
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun spin_lock_irq(&pdata->lock);
227*4882a593Smuzhiyun for (; bytes; bytes--) {
228*4882a593Smuzhiyun __raw_writel(pos++, &rtcreg->adr);
229*4882a593Smuzhiyun __raw_writel(*buf++, &rtcreg->dat);
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun spin_unlock_irq(&pdata->lock);
232*4882a593Smuzhiyun return 0;
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun
tx4939_rtc_probe(struct platform_device * pdev)235*4882a593Smuzhiyun static int __init tx4939_rtc_probe(struct platform_device *pdev)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun struct rtc_device *rtc;
238*4882a593Smuzhiyun struct tx4939rtc_plat_data *pdata;
239*4882a593Smuzhiyun int irq, ret;
240*4882a593Smuzhiyun struct nvmem_config nvmem_cfg = {
241*4882a593Smuzhiyun .name = "tx4939_nvram",
242*4882a593Smuzhiyun .size = TX4939_RTC_REG_RAMSIZE,
243*4882a593Smuzhiyun .reg_read = tx4939_nvram_read,
244*4882a593Smuzhiyun .reg_write = tx4939_nvram_write,
245*4882a593Smuzhiyun };
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun irq = platform_get_irq(pdev, 0);
248*4882a593Smuzhiyun if (irq < 0)
249*4882a593Smuzhiyun return -ENODEV;
250*4882a593Smuzhiyun pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
251*4882a593Smuzhiyun if (!pdata)
252*4882a593Smuzhiyun return -ENOMEM;
253*4882a593Smuzhiyun platform_set_drvdata(pdev, pdata);
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun pdata->rtcreg = devm_platform_ioremap_resource(pdev, 0);
256*4882a593Smuzhiyun if (IS_ERR(pdata->rtcreg))
257*4882a593Smuzhiyun return PTR_ERR(pdata->rtcreg);
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun spin_lock_init(&pdata->lock);
260*4882a593Smuzhiyun tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP);
261*4882a593Smuzhiyun if (devm_request_irq(&pdev->dev, irq, tx4939_rtc_interrupt,
262*4882a593Smuzhiyun 0, pdev->name, &pdev->dev) < 0)
263*4882a593Smuzhiyun return -EBUSY;
264*4882a593Smuzhiyun rtc = devm_rtc_allocate_device(&pdev->dev);
265*4882a593Smuzhiyun if (IS_ERR(rtc))
266*4882a593Smuzhiyun return PTR_ERR(rtc);
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun rtc->ops = &tx4939_rtc_ops;
269*4882a593Smuzhiyun rtc->nvram_old_abi = true;
270*4882a593Smuzhiyun rtc->range_max = U32_MAX;
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun pdata->rtc = rtc;
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun nvmem_cfg.priv = pdata;
275*4882a593Smuzhiyun ret = rtc_nvmem_register(rtc, &nvmem_cfg);
276*4882a593Smuzhiyun if (ret)
277*4882a593Smuzhiyun return ret;
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun return rtc_register_device(rtc);
280*4882a593Smuzhiyun }
281*4882a593Smuzhiyun
tx4939_rtc_remove(struct platform_device * pdev)282*4882a593Smuzhiyun static int __exit tx4939_rtc_remove(struct platform_device *pdev)
283*4882a593Smuzhiyun {
284*4882a593Smuzhiyun struct tx4939rtc_plat_data *pdata = platform_get_drvdata(pdev);
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun spin_lock_irq(&pdata->lock);
287*4882a593Smuzhiyun tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP);
288*4882a593Smuzhiyun spin_unlock_irq(&pdata->lock);
289*4882a593Smuzhiyun return 0;
290*4882a593Smuzhiyun }
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun static struct platform_driver tx4939_rtc_driver = {
293*4882a593Smuzhiyun .remove = __exit_p(tx4939_rtc_remove),
294*4882a593Smuzhiyun .driver = {
295*4882a593Smuzhiyun .name = "tx4939rtc",
296*4882a593Smuzhiyun },
297*4882a593Smuzhiyun };
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun module_platform_driver_probe(tx4939_rtc_driver, tx4939_rtc_probe);
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
302*4882a593Smuzhiyun MODULE_DESCRIPTION("TX4939 internal RTC driver");
303*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
304*4882a593Smuzhiyun MODULE_ALIAS("platform:tx4939rtc");
305