1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (C) 2018, Fuzhou Rockchip Electronics Co., Ltd
4*4882a593Smuzhiyun * Author: Jeffy Chen <jeffy.chen@rock-chips.com>
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Base on the Rockchip timer driver drivers/clocksource/rockchip_timer.c by
7*4882a593Smuzhiyun * Daniel Lezcano <daniel.lezcano@linaro.org>
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/clk.h>
11*4882a593Smuzhiyun #include <linux/kernel.h>
12*4882a593Smuzhiyun #include <linux/module.h>
13*4882a593Smuzhiyun #include <linux/of.h>
14*4882a593Smuzhiyun #include <linux/of_device.h>
15*4882a593Smuzhiyun #include <linux/platform_device.h>
16*4882a593Smuzhiyun #include <linux/regmap.h>
17*4882a593Smuzhiyun #include <linux/rtc.h>
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #define DRV_NAME "rk-timer-rtc"
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun #define TIMER_LOAD_COUNT0 0x00
22*4882a593Smuzhiyun #define TIMER_LOAD_COUNT1 0x04
23*4882a593Smuzhiyun #define TIMER_CURRENT_VALUE0 0x08
24*4882a593Smuzhiyun #define TIMER_CURRENT_VALUE1 0x0C
25*4882a593Smuzhiyun #define TIMER_CONTROL_REG3288 0x10
26*4882a593Smuzhiyun #define TIMER_INT_STATUS 0x18
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun #define TIMER_ENABLE BIT(0)
29*4882a593Smuzhiyun #define TIMER_MODE_USER_DEFINED_COUNT BIT(1)
30*4882a593Smuzhiyun #define TIMER_INT_UNMASK BIT(2)
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun /* Forbid any alarms which would trigger inside the threshold */
33*4882a593Smuzhiyun #define TIMER_ALARM_THRESHOLD_MS 10
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun #if !defined(UINT64_MAX)
36*4882a593Smuzhiyun #define UINT64_MAX ((u64)-1)
37*4882a593Smuzhiyun #endif
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun /**
40*4882a593Smuzhiyun * struct rk_timer_rtc_data - Differences between SoC variants
41*4882a593Smuzhiyun *
42*4882a593Smuzhiyun * @ctrl_reg_offset: The offset of timer control register
43*4882a593Smuzhiyun */
44*4882a593Smuzhiyun struct rk_timer_rtc_data {
45*4882a593Smuzhiyun int ctrl_reg_offset;
46*4882a593Smuzhiyun };
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun /**
49*4882a593Smuzhiyun * struct rk_timer_rtc - Driver data for Rockchip timer RTC
50*4882a593Smuzhiyun *
51*4882a593Smuzhiyun * @data: Pointer to rk_timer_rtc_data
52*4882a593Smuzhiyun * @regmap: Register map of the timer
53*4882a593Smuzhiyun * @rtc: Pointer to RTC device
54*4882a593Smuzhiyun * @clk: The timer clock
55*4882a593Smuzhiyun * @pclk: The peripheral clock
56*4882a593Smuzhiyun * @freq: The freq of timer clock
57*4882a593Smuzhiyun * @timebase: The base time of the timer RTC
58*4882a593Smuzhiyun * @alarm_irq_enabled: Whether to report alarm irqs
59*4882a593Smuzhiyun * @irq: The timer IRQ number
60*4882a593Smuzhiyun */
61*4882a593Smuzhiyun struct rk_timer_rtc {
62*4882a593Smuzhiyun const struct rk_timer_rtc_data *data;
63*4882a593Smuzhiyun struct regmap *regmap;
64*4882a593Smuzhiyun struct rtc_device *rtc;
65*4882a593Smuzhiyun struct clk *clk;
66*4882a593Smuzhiyun struct clk *pclk;
67*4882a593Smuzhiyun u32 freq;
68*4882a593Smuzhiyun u64 timebase;
69*4882a593Smuzhiyun int alarm_irq_enabled;
70*4882a593Smuzhiyun int irq;
71*4882a593Smuzhiyun };
72*4882a593Smuzhiyun
tick_to_sec(struct rk_timer_rtc * rk_timer_rtc,u64 tick)73*4882a593Smuzhiyun static inline u64 tick_to_sec(struct rk_timer_rtc *rk_timer_rtc, u64 tick)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun do_div(tick, rk_timer_rtc->freq);
76*4882a593Smuzhiyun return tick;
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun
ms_to_tick(struct rk_timer_rtc * rk_timer_rtc,int ms)79*4882a593Smuzhiyun static inline u64 ms_to_tick(struct rk_timer_rtc *rk_timer_rtc, int ms)
80*4882a593Smuzhiyun {
81*4882a593Smuzhiyun return ms * rk_timer_rtc->freq / 1000;
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun
tick_to_time64(struct rk_timer_rtc * rk_timer_rtc,u64 tick)84*4882a593Smuzhiyun static inline u64 tick_to_time64(struct rk_timer_rtc *rk_timer_rtc, u64 tick)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun return tick_to_sec(rk_timer_rtc, tick) + rk_timer_rtc->timebase;
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun
time64_to_tick(struct rk_timer_rtc * rk_timer_rtc,u64 time)89*4882a593Smuzhiyun static inline u64 time64_to_tick(struct rk_timer_rtc *rk_timer_rtc, u64 time)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun return (time - rk_timer_rtc->timebase) * rk_timer_rtc->freq;
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun
rk_timer_rtc_write64(struct rk_timer_rtc * rk_timer_rtc,u32 reg,u64 val)94*4882a593Smuzhiyun static inline int rk_timer_rtc_write64(struct rk_timer_rtc *rk_timer_rtc,
95*4882a593Smuzhiyun u32 reg, u64 val)
96*4882a593Smuzhiyun {
97*4882a593Smuzhiyun return regmap_bulk_write(rk_timer_rtc->regmap, reg, &val, 2);
98*4882a593Smuzhiyun }
99*4882a593Smuzhiyun
rk_timer_rtc_read64(struct rk_timer_rtc * rk_timer_rtc,u32 reg,u64 * val)100*4882a593Smuzhiyun static inline int rk_timer_rtc_read64(struct rk_timer_rtc *rk_timer_rtc,
101*4882a593Smuzhiyun u32 reg, u64 *val)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun u32 val_lo, val_hi, tmp_hi;
104*4882a593Smuzhiyun int ret;
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun do {
107*4882a593Smuzhiyun ret = regmap_read(rk_timer_rtc->regmap, reg + 4, &val_hi);
108*4882a593Smuzhiyun if (ret)
109*4882a593Smuzhiyun return ret;
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun ret = regmap_read(rk_timer_rtc->regmap, reg, &val_lo);
112*4882a593Smuzhiyun if (ret)
113*4882a593Smuzhiyun return ret;
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun ret = regmap_read(rk_timer_rtc->regmap, reg + 4, &tmp_hi);
116*4882a593Smuzhiyun if (ret)
117*4882a593Smuzhiyun return ret;
118*4882a593Smuzhiyun } while (val_hi != tmp_hi);
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun *val = ((u64) val_hi << 32) | val_lo;
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun return 0;
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun
rk_timer_rtc_irq_clear(struct rk_timer_rtc * rk_timer_rtc)125*4882a593Smuzhiyun static inline int rk_timer_rtc_irq_clear(struct rk_timer_rtc *rk_timer_rtc)
126*4882a593Smuzhiyun {
127*4882a593Smuzhiyun return regmap_write(rk_timer_rtc->regmap, TIMER_INT_STATUS, 1);
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun
rk_timer_rtc_irq_enable(struct rk_timer_rtc * rk_timer_rtc,unsigned int enabled)130*4882a593Smuzhiyun static inline int rk_timer_rtc_irq_enable(struct rk_timer_rtc *rk_timer_rtc,
131*4882a593Smuzhiyun unsigned int enabled)
132*4882a593Smuzhiyun {
133*4882a593Smuzhiyun /* Clear any pending irq before enable it */
134*4882a593Smuzhiyun if (enabled)
135*4882a593Smuzhiyun rk_timer_rtc_irq_clear(rk_timer_rtc);
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun return regmap_update_bits(rk_timer_rtc->regmap,
138*4882a593Smuzhiyun rk_timer_rtc->data->ctrl_reg_offset,
139*4882a593Smuzhiyun TIMER_INT_UNMASK,
140*4882a593Smuzhiyun enabled ? TIMER_INT_UNMASK : 0);
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun
rk_timer_rtc_reset(struct rk_timer_rtc * rk_timer_rtc)143*4882a593Smuzhiyun static int rk_timer_rtc_reset(struct rk_timer_rtc *rk_timer_rtc)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun int ret;
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun ret = regmap_write(rk_timer_rtc->regmap,
148*4882a593Smuzhiyun rk_timer_rtc->data->ctrl_reg_offset, 0);
149*4882a593Smuzhiyun if (ret)
150*4882a593Smuzhiyun return ret;
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun /* Init load count to UINT64_MAX to keep timer running */
153*4882a593Smuzhiyun ret = rk_timer_rtc_write64(rk_timer_rtc, TIMER_LOAD_COUNT0, UINT64_MAX);
154*4882a593Smuzhiyun if (ret)
155*4882a593Smuzhiyun return ret;
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun /* Clear any pending irq before enable it */
158*4882a593Smuzhiyun rk_timer_rtc_irq_clear(rk_timer_rtc);
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun /* Enable timer in user-defined count mode with irq unmasked */
161*4882a593Smuzhiyun return regmap_write(rk_timer_rtc->regmap,
162*4882a593Smuzhiyun rk_timer_rtc->data->ctrl_reg_offset,
163*4882a593Smuzhiyun TIMER_ENABLE | TIMER_MODE_USER_DEFINED_COUNT |
164*4882a593Smuzhiyun TIMER_INT_UNMASK);
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun
rk_timer_rtc_read_time(struct device * dev,struct rtc_time * tm)167*4882a593Smuzhiyun static int rk_timer_rtc_read_time(struct device *dev, struct rtc_time *tm)
168*4882a593Smuzhiyun {
169*4882a593Smuzhiyun struct rk_timer_rtc *rk_timer_rtc = dev_get_drvdata(dev);
170*4882a593Smuzhiyun int ret;
171*4882a593Smuzhiyun u64 tick;
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun ret = rk_timer_rtc_read64(rk_timer_rtc, TIMER_CURRENT_VALUE0, &tick);
174*4882a593Smuzhiyun if (ret)
175*4882a593Smuzhiyun return ret;
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun rtc_time64_to_tm(tick_to_time64(rk_timer_rtc, tick), tm);
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun dev_dbg(dev, "Read RTC: %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
180*4882a593Smuzhiyun 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
181*4882a593Smuzhiyun tm->tm_wday, tm->tm_hour, tm->tm_min, tm->tm_sec);
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun return rtc_valid_tm(tm);
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun
rk_timer_rtc_set_time(struct device * dev,struct rtc_time * tm)186*4882a593Smuzhiyun static int rk_timer_rtc_set_time(struct device *dev, struct rtc_time *tm)
187*4882a593Smuzhiyun {
188*4882a593Smuzhiyun struct rk_timer_rtc *rk_timer_rtc = dev_get_drvdata(dev);
189*4882a593Smuzhiyun int ret;
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun dev_dbg(dev, "Set RTC:%4d-%02d-%02d(%d) %02d:%02d:%02d\n",
192*4882a593Smuzhiyun 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
193*4882a593Smuzhiyun tm->tm_wday, tm->tm_hour, tm->tm_min, tm->tm_sec);
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun ret = rtc_valid_tm(tm);
196*4882a593Smuzhiyun if (ret)
197*4882a593Smuzhiyun return ret;
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun rk_timer_rtc->timebase = rtc_tm_to_time64(tm);
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun dev_dbg(dev, "Setting new timebase:%lld\n", rk_timer_rtc->timebase);
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun /* Restart timer for new timebase */
204*4882a593Smuzhiyun ret = rk_timer_rtc_reset(rk_timer_rtc);
205*4882a593Smuzhiyun if (ret) {
206*4882a593Smuzhiyun dev_err(dev, "Failed to reset timer:%d\n", ret);
207*4882a593Smuzhiyun return ret;
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun /* Tell framework to check alarms */
211*4882a593Smuzhiyun rtc_update_irq(rk_timer_rtc->rtc, 1, RTC_IRQF | RTC_AF);
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun return 0;
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun
rk_timer_rtc_read_alarm(struct device * dev,struct rtc_wkalrm * alrm)216*4882a593Smuzhiyun static int rk_timer_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
217*4882a593Smuzhiyun {
218*4882a593Smuzhiyun struct rk_timer_rtc *rk_timer_rtc = dev_get_drvdata(dev);
219*4882a593Smuzhiyun int ret;
220*4882a593Smuzhiyun u64 tick;
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun ret = rk_timer_rtc_read64(rk_timer_rtc, TIMER_LOAD_COUNT0, &tick);
223*4882a593Smuzhiyun if (ret)
224*4882a593Smuzhiyun return ret;
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun rtc_time64_to_tm(tick_to_time64(rk_timer_rtc, tick), &alrm->time);
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun dev_dbg(dev, "Read alarm: %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
229*4882a593Smuzhiyun 1900 + alrm->time.tm_year, alrm->time.tm_mon + 1,
230*4882a593Smuzhiyun alrm->time.tm_mday, alrm->time.tm_wday, alrm->time.tm_hour,
231*4882a593Smuzhiyun alrm->time.tm_min, alrm->time.tm_sec);
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun return rtc_valid_tm(&alrm->time);
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun
rk_timer_rtc_set_alarm(struct device * dev,struct rtc_wkalrm * alrm)236*4882a593Smuzhiyun static int rk_timer_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
237*4882a593Smuzhiyun {
238*4882a593Smuzhiyun struct rk_timer_rtc *rk_timer_rtc = dev_get_drvdata(dev);
239*4882a593Smuzhiyun int ret;
240*4882a593Smuzhiyun u64 alarm_tick, alarm_threshold_tick, cur_tick;
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun dev_dbg(dev, "Set alarm:%4d-%02d-%02d(%d) %02d:%02d:%02d\n",
243*4882a593Smuzhiyun 1900 + alrm->time.tm_year, alrm->time.tm_mon + 1,
244*4882a593Smuzhiyun alrm->time.tm_mday, alrm->time.tm_wday, alrm->time.tm_hour,
245*4882a593Smuzhiyun alrm->time.tm_min, alrm->time.tm_sec);
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun ret = rtc_valid_tm(&alrm->time);
248*4882a593Smuzhiyun if (ret)
249*4882a593Smuzhiyun return ret;
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun rk_timer_rtc->alarm_irq_enabled = false;
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun alarm_tick = time64_to_tick(rk_timer_rtc,
254*4882a593Smuzhiyun rtc_tm_to_time64(&alrm->time));
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun ret = rk_timer_rtc_read64(rk_timer_rtc, TIMER_CURRENT_VALUE0,
257*4882a593Smuzhiyun &cur_tick);
258*4882a593Smuzhiyun if (ret)
259*4882a593Smuzhiyun return ret;
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun /* Don't set an alarm in the past or about to pass */
262*4882a593Smuzhiyun alarm_threshold_tick = ms_to_tick(rk_timer_rtc,
263*4882a593Smuzhiyun TIMER_ALARM_THRESHOLD_MS);
264*4882a593Smuzhiyun if (alarm_tick <= (cur_tick + alarm_threshold_tick))
265*4882a593Smuzhiyun return -ETIME;
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun /*
268*4882a593Smuzhiyun * When the current value counts up to the load count, the timer will
269*4882a593Smuzhiyun * stop and generate an irq.
270*4882a593Smuzhiyun */
271*4882a593Smuzhiyun ret = rk_timer_rtc_write64(rk_timer_rtc, TIMER_LOAD_COUNT0, alarm_tick);
272*4882a593Smuzhiyun if (ret)
273*4882a593Smuzhiyun return ret;
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun dev_dbg(dev, "New alarm enabled:%d\n", alrm->enabled);
276*4882a593Smuzhiyun rk_timer_rtc->alarm_irq_enabled = alrm->enabled;
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun return 0;
279*4882a593Smuzhiyun }
280*4882a593Smuzhiyun
rk_timer_rtc_alarm_irq_enable(struct device * dev,unsigned int enabled)281*4882a593Smuzhiyun static int rk_timer_rtc_alarm_irq_enable(struct device *dev,
282*4882a593Smuzhiyun unsigned int enabled)
283*4882a593Smuzhiyun {
284*4882a593Smuzhiyun struct rk_timer_rtc *rk_timer_rtc = dev_get_drvdata(dev);
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun dev_dbg(dev, "Set alarm irq enabled:%d\n", enabled);
287*4882a593Smuzhiyun rk_timer_rtc->alarm_irq_enabled = enabled;
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun return 0;
290*4882a593Smuzhiyun }
291*4882a593Smuzhiyun
rk_timer_rtc_alarm_irq(int irq,void * data)292*4882a593Smuzhiyun static irqreturn_t rk_timer_rtc_alarm_irq(int irq, void *data)
293*4882a593Smuzhiyun {
294*4882a593Smuzhiyun struct device *dev = data;
295*4882a593Smuzhiyun struct rk_timer_rtc *rk_timer_rtc = dev_get_drvdata(dev);
296*4882a593Smuzhiyun int ret;
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun dev_dbg(dev, "Received timer irq, alarm_irq_enabled:%d\n",
299*4882a593Smuzhiyun rk_timer_rtc->alarm_irq_enabled);
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun /* The timer is stopped now, reset the load count to start it again */
302*4882a593Smuzhiyun ret = rk_timer_rtc_write64(rk_timer_rtc, TIMER_LOAD_COUNT0, UINT64_MAX);
303*4882a593Smuzhiyun if (ret)
304*4882a593Smuzhiyun dev_err(dev, "Failed to set load count:%d\n", ret);
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun ret = regmap_write(rk_timer_rtc->regmap, TIMER_INT_STATUS, 1);
307*4882a593Smuzhiyun if (ret)
308*4882a593Smuzhiyun dev_err(dev, "Failed to clear irq:%d\n", ret);
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun /* Only report rtc irq when alarm irq is enabled */
311*4882a593Smuzhiyun if (rk_timer_rtc->alarm_irq_enabled)
312*4882a593Smuzhiyun rtc_update_irq(rk_timer_rtc->rtc, 1, RTC_IRQF | RTC_AF);
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun return IRQ_HANDLED;
315*4882a593Smuzhiyun }
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun static const struct rtc_class_ops rk_timer_rtc_ops = {
318*4882a593Smuzhiyun .read_time = rk_timer_rtc_read_time,
319*4882a593Smuzhiyun .set_time = rk_timer_rtc_set_time,
320*4882a593Smuzhiyun .read_alarm = rk_timer_rtc_read_alarm,
321*4882a593Smuzhiyun .set_alarm = rk_timer_rtc_set_alarm,
322*4882a593Smuzhiyun .alarm_irq_enable = rk_timer_rtc_alarm_irq_enable,
323*4882a593Smuzhiyun };
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun static struct regmap_config rk_timer_regmap_config = {
326*4882a593Smuzhiyun .name = DRV_NAME,
327*4882a593Smuzhiyun .reg_bits = 32,
328*4882a593Smuzhiyun .val_bits = 32,
329*4882a593Smuzhiyun .reg_stride = 4,
330*4882a593Smuzhiyun };
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun static const struct of_device_id rk_timer_rtc_dt_match[];
333*4882a593Smuzhiyun
rk_timer_rtc_probe(struct platform_device * pdev)334*4882a593Smuzhiyun static int rk_timer_rtc_probe(struct platform_device *pdev)
335*4882a593Smuzhiyun {
336*4882a593Smuzhiyun const struct of_device_id *match;
337*4882a593Smuzhiyun struct device *dev = &pdev->dev;
338*4882a593Smuzhiyun struct rk_timer_rtc *rk_timer_rtc;
339*4882a593Smuzhiyun void __iomem *base;
340*4882a593Smuzhiyun resource_size_t size;
341*4882a593Smuzhiyun int ret;
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun rk_timer_rtc = devm_kzalloc(dev, sizeof(*rk_timer_rtc), GFP_KERNEL);
344*4882a593Smuzhiyun if (!rk_timer_rtc)
345*4882a593Smuzhiyun return -ENOMEM;
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun match = of_match_node(rk_timer_rtc_dt_match, dev->of_node);
348*4882a593Smuzhiyun rk_timer_rtc->data = match->data;
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun platform_set_drvdata(pdev, rk_timer_rtc);
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun base = devm_of_iomap(dev, dev->of_node, 0, &size);
353*4882a593Smuzhiyun if (!base) {
354*4882a593Smuzhiyun dev_err(dev, "Failed to iomap\n");
355*4882a593Smuzhiyun return -EINVAL;
356*4882a593Smuzhiyun }
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun rk_timer_regmap_config.max_register = size - 4;
359*4882a593Smuzhiyun rk_timer_rtc->regmap = devm_regmap_init_mmio(dev, base,
360*4882a593Smuzhiyun &rk_timer_regmap_config);
361*4882a593Smuzhiyun if (IS_ERR(rk_timer_rtc->regmap)) {
362*4882a593Smuzhiyun ret = PTR_ERR(rk_timer_rtc->regmap);
363*4882a593Smuzhiyun dev_err(dev, "Failed to init regmap:%d\n", ret);
364*4882a593Smuzhiyun return ret;
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun rk_timer_rtc->irq = platform_get_irq(pdev, 0);
368*4882a593Smuzhiyun if (rk_timer_rtc->irq < 0) {
369*4882a593Smuzhiyun ret = rk_timer_rtc->irq;
370*4882a593Smuzhiyun dev_err(dev, "Failed to get irq:%d\n", ret);
371*4882a593Smuzhiyun return ret;
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun ret = devm_request_irq(dev, rk_timer_rtc->irq, rk_timer_rtc_alarm_irq,
375*4882a593Smuzhiyun 0, dev_name(dev), dev);
376*4882a593Smuzhiyun if (ret) {
377*4882a593Smuzhiyun dev_err(dev, "Failed to request irq:%d\n", ret);
378*4882a593Smuzhiyun return ret;
379*4882a593Smuzhiyun }
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun rk_timer_rtc->pclk = devm_clk_get(dev, "pclk");
382*4882a593Smuzhiyun if (IS_ERR(rk_timer_rtc->pclk)) {
383*4882a593Smuzhiyun ret = PTR_ERR(rk_timer_rtc->pclk);
384*4882a593Smuzhiyun pr_err("Failed to get timer pclk:%d\n", ret);
385*4882a593Smuzhiyun return ret;
386*4882a593Smuzhiyun }
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun ret = clk_prepare_enable(rk_timer_rtc->pclk);
389*4882a593Smuzhiyun if (ret) {
390*4882a593Smuzhiyun dev_err(dev, "Failed to enable pclk:%d\n", ret);
391*4882a593Smuzhiyun return ret;
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun rk_timer_rtc->clk = devm_clk_get(dev, "timer");
395*4882a593Smuzhiyun if (IS_ERR(rk_timer_rtc->clk)) {
396*4882a593Smuzhiyun ret = PTR_ERR(rk_timer_rtc->clk);
397*4882a593Smuzhiyun pr_err("Failed to get timer clk:%d\n", ret);
398*4882a593Smuzhiyun goto err_disable_pclk;
399*4882a593Smuzhiyun }
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun ret = clk_prepare_enable(rk_timer_rtc->clk);
402*4882a593Smuzhiyun if (ret) {
403*4882a593Smuzhiyun dev_err(dev, "Failed to enable timer clk:%d\n", ret);
404*4882a593Smuzhiyun goto err_disable_pclk;
405*4882a593Smuzhiyun }
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun rk_timer_rtc->freq = clk_get_rate(rk_timer_rtc->clk);
408*4882a593Smuzhiyun dev_dbg(dev, "RTC timer freq:%d\n", rk_timer_rtc->freq);
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun ret = rk_timer_rtc_reset(rk_timer_rtc);
411*4882a593Smuzhiyun if (ret) {
412*4882a593Smuzhiyun dev_err(dev, "Failed to reset timer:%d\n", ret);
413*4882a593Smuzhiyun goto err_disable_clk;
414*4882a593Smuzhiyun }
415*4882a593Smuzhiyun
416*4882a593Smuzhiyun ret = device_init_wakeup(dev, true);
417*4882a593Smuzhiyun if (ret) {
418*4882a593Smuzhiyun dev_err(dev, "Failed to init wakeup:%d\n", ret);
419*4882a593Smuzhiyun goto err_disable_irq;
420*4882a593Smuzhiyun }
421*4882a593Smuzhiyun
422*4882a593Smuzhiyun rk_timer_rtc->rtc = devm_rtc_device_register(dev, DRV_NAME,
423*4882a593Smuzhiyun &rk_timer_rtc_ops,
424*4882a593Smuzhiyun THIS_MODULE);
425*4882a593Smuzhiyun if (IS_ERR(rk_timer_rtc->rtc)) {
426*4882a593Smuzhiyun ret = PTR_ERR(rk_timer_rtc->rtc);
427*4882a593Smuzhiyun dev_err(dev, "Failed to register rtc:%d\n", ret);
428*4882a593Smuzhiyun goto err_uninit_wakeup;
429*4882a593Smuzhiyun }
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun return 0;
432*4882a593Smuzhiyun err_uninit_wakeup:
433*4882a593Smuzhiyun device_init_wakeup(&pdev->dev, false);
434*4882a593Smuzhiyun err_disable_irq:
435*4882a593Smuzhiyun rk_timer_rtc_irq_enable(rk_timer_rtc, false);
436*4882a593Smuzhiyun err_disable_clk:
437*4882a593Smuzhiyun clk_disable_unprepare(rk_timer_rtc->clk);
438*4882a593Smuzhiyun err_disable_pclk:
439*4882a593Smuzhiyun clk_disable_unprepare(rk_timer_rtc->pclk);
440*4882a593Smuzhiyun return ret;
441*4882a593Smuzhiyun }
442*4882a593Smuzhiyun
rk_timer_rtc_remove(struct platform_device * pdev)443*4882a593Smuzhiyun static int rk_timer_rtc_remove(struct platform_device *pdev)
444*4882a593Smuzhiyun {
445*4882a593Smuzhiyun struct rk_timer_rtc *rk_timer_rtc = dev_get_drvdata(&pdev->dev);
446*4882a593Smuzhiyun
447*4882a593Smuzhiyun device_init_wakeup(&pdev->dev, false);
448*4882a593Smuzhiyun rk_timer_rtc_irq_enable(rk_timer_rtc, false);
449*4882a593Smuzhiyun clk_disable_unprepare(rk_timer_rtc->clk);
450*4882a593Smuzhiyun clk_disable_unprepare(rk_timer_rtc->pclk);
451*4882a593Smuzhiyun
452*4882a593Smuzhiyun return 0;
453*4882a593Smuzhiyun }
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
rk_timer_rtc_suspend(struct device * dev)456*4882a593Smuzhiyun static int rk_timer_rtc_suspend(struct device *dev)
457*4882a593Smuzhiyun {
458*4882a593Smuzhiyun struct rk_timer_rtc *rk_timer_rtc = dev_get_drvdata(dev);
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun if (device_may_wakeup(dev))
461*4882a593Smuzhiyun enable_irq_wake(rk_timer_rtc->irq);
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun return 0;
464*4882a593Smuzhiyun }
465*4882a593Smuzhiyun
rk_timer_rtc_resume(struct device * dev)466*4882a593Smuzhiyun static int rk_timer_rtc_resume(struct device *dev)
467*4882a593Smuzhiyun {
468*4882a593Smuzhiyun struct rk_timer_rtc *rk_timer_rtc = dev_get_drvdata(dev);
469*4882a593Smuzhiyun
470*4882a593Smuzhiyun if (device_may_wakeup(dev))
471*4882a593Smuzhiyun disable_irq_wake(rk_timer_rtc->irq);
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun return 0;
474*4882a593Smuzhiyun }
475*4882a593Smuzhiyun #endif
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun static SIMPLE_DEV_PM_OPS(rk_timer_rtc_pm_ops, rk_timer_rtc_suspend,
478*4882a593Smuzhiyun rk_timer_rtc_resume);
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun static const struct rk_timer_rtc_data rk3288_timer_rtc_data = {
481*4882a593Smuzhiyun .ctrl_reg_offset = TIMER_CONTROL_REG3288,
482*4882a593Smuzhiyun };
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun static const struct of_device_id rk_timer_rtc_dt_match[] = {
485*4882a593Smuzhiyun {
486*4882a593Smuzhiyun .compatible = "rockchip,rk3308-timer-rtc",
487*4882a593Smuzhiyun .data = &rk3288_timer_rtc_data,
488*4882a593Smuzhiyun },
489*4882a593Smuzhiyun { /* sentinel */ }
490*4882a593Smuzhiyun };
491*4882a593Smuzhiyun MODULE_DEVICE_TABLE(platform, rk_timer_rtc_dt_match);
492*4882a593Smuzhiyun
493*4882a593Smuzhiyun static struct platform_driver rk_timer_rtc_driver = {
494*4882a593Smuzhiyun .probe = rk_timer_rtc_probe,
495*4882a593Smuzhiyun .remove = rk_timer_rtc_remove,
496*4882a593Smuzhiyun .driver = {
497*4882a593Smuzhiyun .name = DRV_NAME,
498*4882a593Smuzhiyun .pm = &rk_timer_rtc_pm_ops,
499*4882a593Smuzhiyun .of_match_table = of_match_ptr(rk_timer_rtc_dt_match),
500*4882a593Smuzhiyun },
501*4882a593Smuzhiyun };
502*4882a593Smuzhiyun
503*4882a593Smuzhiyun module_platform_driver(rk_timer_rtc_driver);
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun MODULE_DESCRIPTION("RTC driver for the rockchip timer");
506*4882a593Smuzhiyun MODULE_AUTHOR("Jeffy Chen <jeffy.chen@rock-chips.com>");
507*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
508*4882a593Smuzhiyun MODULE_ALIAS("platform:" DRV_NAME);
509