Merge tag 'mips_6.3_1' of git://git.kernel.org/pub/scm/linux/kernel/git/mips/linux
[linux-block.git] / drivers / rtc / rtc-goldfish.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* drivers/rtc/rtc-goldfish.c
3  *
4  * Copyright (C) 2007 Google, Inc.
5  * Copyright (C) 2017 Imagination Technologies Ltd.
6  */
7
8 #include <linux/io.h>
9 #include <linux/module.h>
10 #include <linux/of.h>
11 #include <linux/platform_device.h>
12 #include <linux/rtc.h>
13 #include <linux/goldfish.h>
14 #include <clocksource/timer-goldfish.h>
15
16 struct goldfish_rtc {
17         void __iomem *base;
18         int irq;
19         struct rtc_device *rtc;
20 };
21
22 static int goldfish_rtc_read_alarm(struct device *dev,
23                                    struct rtc_wkalrm *alrm)
24 {
25         u64 rtc_alarm;
26         u64 rtc_alarm_low;
27         u64 rtc_alarm_high;
28         void __iomem *base;
29         struct goldfish_rtc *rtcdrv;
30
31         rtcdrv = dev_get_drvdata(dev);
32         base = rtcdrv->base;
33
34         rtc_alarm_low = gf_ioread32(base + TIMER_ALARM_LOW);
35         rtc_alarm_high = gf_ioread32(base + TIMER_ALARM_HIGH);
36         rtc_alarm = (rtc_alarm_high << 32) | rtc_alarm_low;
37
38         do_div(rtc_alarm, NSEC_PER_SEC);
39         memset(alrm, 0, sizeof(struct rtc_wkalrm));
40
41         rtc_time64_to_tm(rtc_alarm, &alrm->time);
42
43         if (gf_ioread32(base + TIMER_ALARM_STATUS))
44                 alrm->enabled = 1;
45         else
46                 alrm->enabled = 0;
47
48         return 0;
49 }
50
51 static int goldfish_rtc_set_alarm(struct device *dev,
52                                   struct rtc_wkalrm *alrm)
53 {
54         struct goldfish_rtc *rtcdrv;
55         u64 rtc_alarm64;
56         u64 rtc_status_reg;
57         void __iomem *base;
58
59         rtcdrv = dev_get_drvdata(dev);
60         base = rtcdrv->base;
61
62         if (alrm->enabled) {
63                 rtc_alarm64 = rtc_tm_to_time64(&alrm->time) * NSEC_PER_SEC;
64                 gf_iowrite32((rtc_alarm64 >> 32), base + TIMER_ALARM_HIGH);
65                 gf_iowrite32(rtc_alarm64, base + TIMER_ALARM_LOW);
66                 gf_iowrite32(1, base + TIMER_IRQ_ENABLED);
67         } else {
68                 /*
69                  * if this function was called with enabled=0
70                  * then it could mean that the application is
71                  * trying to cancel an ongoing alarm
72                  */
73                 rtc_status_reg = gf_ioread32(base + TIMER_ALARM_STATUS);
74                 if (rtc_status_reg)
75                         gf_iowrite32(1, base + TIMER_CLEAR_ALARM);
76         }
77
78         return 0;
79 }
80
81 static int goldfish_rtc_alarm_irq_enable(struct device *dev,
82                                          unsigned int enabled)
83 {
84         void __iomem *base;
85         struct goldfish_rtc *rtcdrv;
86
87         rtcdrv = dev_get_drvdata(dev);
88         base = rtcdrv->base;
89
90         if (enabled)
91                 gf_iowrite32(1, base + TIMER_IRQ_ENABLED);
92         else
93                 gf_iowrite32(0, base + TIMER_IRQ_ENABLED);
94
95         return 0;
96 }
97
98 static irqreturn_t goldfish_rtc_interrupt(int irq, void *dev_id)
99 {
100         struct goldfish_rtc *rtcdrv = dev_id;
101         void __iomem *base = rtcdrv->base;
102
103         gf_iowrite32(1, base + TIMER_CLEAR_INTERRUPT);
104
105         rtc_update_irq(rtcdrv->rtc, 1, RTC_IRQF | RTC_AF);
106
107         return IRQ_HANDLED;
108 }
109
110 static int goldfish_rtc_read_time(struct device *dev, struct rtc_time *tm)
111 {
112         struct goldfish_rtc *rtcdrv;
113         void __iomem *base;
114         u64 time_high;
115         u64 time_low;
116         u64 time;
117
118         rtcdrv = dev_get_drvdata(dev);
119         base = rtcdrv->base;
120
121         time_low = gf_ioread32(base + TIMER_TIME_LOW);
122         time_high = gf_ioread32(base + TIMER_TIME_HIGH);
123         time = (time_high << 32) | time_low;
124
125         do_div(time, NSEC_PER_SEC);
126
127         rtc_time64_to_tm(time, tm);
128
129         return 0;
130 }
131
132 static int goldfish_rtc_set_time(struct device *dev, struct rtc_time *tm)
133 {
134         struct goldfish_rtc *rtcdrv;
135         void __iomem *base;
136         u64 now64;
137
138         rtcdrv = dev_get_drvdata(dev);
139         base = rtcdrv->base;
140
141         now64 = rtc_tm_to_time64(tm) * NSEC_PER_SEC;
142         gf_iowrite32((now64 >> 32), base + TIMER_TIME_HIGH);
143         gf_iowrite32(now64, base + TIMER_TIME_LOW);
144
145         return 0;
146 }
147
148 static const struct rtc_class_ops goldfish_rtc_ops = {
149         .read_time      = goldfish_rtc_read_time,
150         .set_time       = goldfish_rtc_set_time,
151         .read_alarm     = goldfish_rtc_read_alarm,
152         .set_alarm      = goldfish_rtc_set_alarm,
153         .alarm_irq_enable = goldfish_rtc_alarm_irq_enable
154 };
155
156 static int goldfish_rtc_probe(struct platform_device *pdev)
157 {
158         struct goldfish_rtc *rtcdrv;
159         int err;
160
161         rtcdrv = devm_kzalloc(&pdev->dev, sizeof(*rtcdrv), GFP_KERNEL);
162         if (!rtcdrv)
163                 return -ENOMEM;
164
165         platform_set_drvdata(pdev, rtcdrv);
166         rtcdrv->base = devm_platform_ioremap_resource(pdev, 0);
167         if (IS_ERR(rtcdrv->base))
168                 return PTR_ERR(rtcdrv->base);
169
170         rtcdrv->irq = platform_get_irq(pdev, 0);
171         if (rtcdrv->irq < 0)
172                 return -ENODEV;
173
174         rtcdrv->rtc = devm_rtc_allocate_device(&pdev->dev);
175         if (IS_ERR(rtcdrv->rtc))
176                 return PTR_ERR(rtcdrv->rtc);
177
178         rtcdrv->rtc->ops = &goldfish_rtc_ops;
179         rtcdrv->rtc->range_max = U64_MAX / NSEC_PER_SEC;
180
181         err = devm_request_irq(&pdev->dev, rtcdrv->irq,
182                                goldfish_rtc_interrupt,
183                                0, pdev->name, rtcdrv);
184         if (err)
185                 return err;
186
187         return devm_rtc_register_device(rtcdrv->rtc);
188 }
189
190 static const struct of_device_id goldfish_rtc_of_match[] = {
191         { .compatible = "google,goldfish-rtc", },
192         {},
193 };
194 MODULE_DEVICE_TABLE(of, goldfish_rtc_of_match);
195
196 static struct platform_driver goldfish_rtc = {
197         .probe = goldfish_rtc_probe,
198         .driver = {
199                 .name = "goldfish_rtc",
200                 .of_match_table = goldfish_rtc_of_match,
201         }
202 };
203
204 module_platform_driver(goldfish_rtc);
205
206 MODULE_LICENSE("GPL v2");