Commit | Line | Data |
---|---|---|
2025cf9e | 1 | // SPDX-License-Identifier: GPL-2.0-only |
3ca1e326 CZ |
2 | /* |
3 | * RTC driver for Rockchip RK808 | |
4 | * | |
5 | * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd | |
6 | * | |
7 | * Author: Chris Zhong <zyw@rock-chips.com> | |
8 | * Author: Zhang Qing <zhangqing@rock-chips.com> | |
3ca1e326 CZ |
9 | */ |
10 | ||
11 | #include <linux/module.h> | |
12 | #include <linux/kernel.h> | |
13 | #include <linux/rtc.h> | |
14 | #include <linux/bcd.h> | |
15 | #include <linux/mfd/rk808.h> | |
16 | #include <linux/platform_device.h> | |
3ca1e326 CZ |
17 | |
18 | /* RTC_CTRL_REG bitfields */ | |
19 | #define BIT_RTC_CTRL_REG_STOP_RTC_M BIT(0) | |
20 | ||
21 | /* RK808 has a shadowed register for saving a "frozen" RTC time. | |
22 | * When user setting "GET_TIME" to 1, the time will save in this shadowed | |
23 | * register. If set "READSEL" to 1, user read rtc time register, actually | |
24 | * get the time of that moment. If we need the real time, clr this bit. | |
25 | */ | |
26 | #define BIT_RTC_CTRL_REG_RTC_GET_TIME BIT(6) | |
27 | #define BIT_RTC_CTRL_REG_RTC_READSEL_M BIT(7) | |
28 | #define BIT_RTC_INTERRUPTS_REG_IT_ALARM_M BIT(3) | |
29 | #define RTC_STATUS_MASK 0xFE | |
30 | ||
31 | #define SECONDS_REG_MSK 0x7F | |
32 | #define MINUTES_REG_MAK 0x7F | |
33 | #define HOURS_REG_MSK 0x3F | |
34 | #define DAYS_REG_MSK 0x3F | |
35 | #define MONTHS_REG_MSK 0x1F | |
36 | #define YEARS_REG_MSK 0xFF | |
37 | #define WEEKS_REG_MSK 0x7 | |
38 | ||
39 | /* REG_SECONDS_REG through REG_YEARS_REG is how many registers? */ | |
40 | ||
41 | #define NUM_TIME_REGS (RK808_WEEKS_REG - RK808_SECONDS_REG + 1) | |
42 | #define NUM_ALARM_REGS (RK808_ALARM_YEARS_REG - RK808_ALARM_SECONDS_REG + 1) | |
43 | ||
dc79054a TX |
44 | struct rk_rtc_compat_reg { |
45 | unsigned int ctrl_reg; | |
46 | unsigned int status_reg; | |
47 | unsigned int alarm_seconds_reg; | |
48 | unsigned int int_reg; | |
49 | unsigned int seconds_reg; | |
50 | }; | |
51 | ||
3ca1e326 | 52 | struct rk808_rtc { |
2e830ccc | 53 | struct regmap *regmap; |
3ca1e326 | 54 | struct rtc_device *rtc; |
dc79054a | 55 | struct rk_rtc_compat_reg *creg; |
3ca1e326 CZ |
56 | int irq; |
57 | }; | |
58 | ||
f076ef44 JW |
59 | /* |
60 | * The Rockchip calendar used by the RK808 counts November with 31 days. We use | |
61 | * these translation functions to convert its dates to/from the Gregorian | |
62 | * calendar used by the rest of the world. We arbitrarily define Jan 1st, 2016 | |
63 | * as the day when both calendars were in sync, and treat all other dates | |
64 | * relative to that. | |
65 | * NOTE: Other system software (e.g. firmware) that reads the same hardware must | |
66 | * implement this exact same conversion algorithm, with the same anchor date. | |
67 | */ | |
68 | static time64_t nov2dec_transitions(struct rtc_time *tm) | |
69 | { | |
70 | return (tm->tm_year + 1900) - 2016 + (tm->tm_mon + 1 > 11 ? 1 : 0); | |
71 | } | |
72 | ||
73 | static void rockchip_to_gregorian(struct rtc_time *tm) | |
74 | { | |
75 | /* If it's Nov 31st, rtc_tm_to_time64() will count that like Dec 1st */ | |
76 | time64_t time = rtc_tm_to_time64(tm); | |
77 | rtc_time64_to_tm(time + nov2dec_transitions(tm) * 86400, tm); | |
78 | } | |
79 | ||
80 | static void gregorian_to_rockchip(struct rtc_time *tm) | |
81 | { | |
82 | time64_t extra_days = nov2dec_transitions(tm); | |
83 | time64_t time = rtc_tm_to_time64(tm); | |
84 | rtc_time64_to_tm(time - extra_days * 86400, tm); | |
85 | ||
86 | /* Compensate if we went back over Nov 31st (will work up to 2381) */ | |
87 | if (nov2dec_transitions(tm) < extra_days) { | |
88 | if (tm->tm_mon + 1 == 11) | |
89 | tm->tm_mday++; /* This may result in 31! */ | |
90 | else | |
91 | rtc_time64_to_tm(time - (extra_days - 1) * 86400, tm); | |
92 | } | |
93 | } | |
94 | ||
3ca1e326 CZ |
95 | /* Read current time and date in RTC */ |
96 | static int rk808_rtc_readtime(struct device *dev, struct rtc_time *tm) | |
97 | { | |
98 | struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev); | |
3ca1e326 CZ |
99 | u8 rtc_data[NUM_TIME_REGS]; |
100 | int ret; | |
101 | ||
102 | /* Force an update of the shadowed registers right now */ | |
2e830ccc | 103 | ret = regmap_update_bits(rk808_rtc->regmap, rk808_rtc->creg->ctrl_reg, |
3ca1e326 | 104 | BIT_RTC_CTRL_REG_RTC_GET_TIME, |
c412c603 | 105 | BIT_RTC_CTRL_REG_RTC_GET_TIME); |
3ca1e326 CZ |
106 | if (ret) { |
107 | dev_err(dev, "Failed to update bits rtc_ctrl: %d\n", ret); | |
108 | return ret; | |
109 | } | |
110 | ||
c412c603 CZ |
111 | /* |
112 | * After we set the GET_TIME bit, the rtc time can't be read | |
113 | * immediately. So we should wait up to 31.25 us, about one cycle of | |
114 | * 32khz. If we clear the GET_TIME bit here, the time of i2c transfer | |
115 | * certainly more than 31.25us: 16 * 2.5us at 400kHz bus frequency. | |
116 | */ | |
2e830ccc | 117 | ret = regmap_update_bits(rk808_rtc->regmap, rk808_rtc->creg->ctrl_reg, |
3ca1e326 | 118 | BIT_RTC_CTRL_REG_RTC_GET_TIME, |
c412c603 | 119 | 0); |
3ca1e326 CZ |
120 | if (ret) { |
121 | dev_err(dev, "Failed to update bits rtc_ctrl: %d\n", ret); | |
122 | return ret; | |
123 | } | |
124 | ||
2e830ccc | 125 | ret = regmap_bulk_read(rk808_rtc->regmap, rk808_rtc->creg->seconds_reg, |
3ca1e326 CZ |
126 | rtc_data, NUM_TIME_REGS); |
127 | if (ret) { | |
128 | dev_err(dev, "Failed to bulk read rtc_data: %d\n", ret); | |
129 | return ret; | |
130 | } | |
131 | ||
132 | tm->tm_sec = bcd2bin(rtc_data[0] & SECONDS_REG_MSK); | |
133 | tm->tm_min = bcd2bin(rtc_data[1] & MINUTES_REG_MAK); | |
134 | tm->tm_hour = bcd2bin(rtc_data[2] & HOURS_REG_MSK); | |
135 | tm->tm_mday = bcd2bin(rtc_data[3] & DAYS_REG_MSK); | |
136 | tm->tm_mon = (bcd2bin(rtc_data[4] & MONTHS_REG_MSK)) - 1; | |
137 | tm->tm_year = (bcd2bin(rtc_data[5] & YEARS_REG_MSK)) + 100; | |
138 | tm->tm_wday = bcd2bin(rtc_data[6] & WEEKS_REG_MSK); | |
f076ef44 | 139 | rockchip_to_gregorian(tm); |
0991e754 | 140 | dev_dbg(dev, "RTC date/time %ptRd(%d) %ptRt\n", tm, tm->tm_wday, tm); |
3ca1e326 CZ |
141 | |
142 | return ret; | |
143 | } | |
144 | ||
145 | /* Set current time and date in RTC */ | |
146 | static int rk808_rtc_set_time(struct device *dev, struct rtc_time *tm) | |
147 | { | |
148 | struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev); | |
3ca1e326 CZ |
149 | u8 rtc_data[NUM_TIME_REGS]; |
150 | int ret; | |
151 | ||
0991e754 | 152 | dev_dbg(dev, "set RTC date/time %ptRd(%d) %ptRt\n", tm, tm->tm_wday, tm); |
f076ef44 | 153 | gregorian_to_rockchip(tm); |
3ca1e326 CZ |
154 | rtc_data[0] = bin2bcd(tm->tm_sec); |
155 | rtc_data[1] = bin2bcd(tm->tm_min); | |
156 | rtc_data[2] = bin2bcd(tm->tm_hour); | |
157 | rtc_data[3] = bin2bcd(tm->tm_mday); | |
158 | rtc_data[4] = bin2bcd(tm->tm_mon + 1); | |
159 | rtc_data[5] = bin2bcd(tm->tm_year - 100); | |
160 | rtc_data[6] = bin2bcd(tm->tm_wday); | |
3ca1e326 CZ |
161 | |
162 | /* Stop RTC while updating the RTC registers */ | |
2e830ccc | 163 | ret = regmap_update_bits(rk808_rtc->regmap, rk808_rtc->creg->ctrl_reg, |
3ca1e326 CZ |
164 | BIT_RTC_CTRL_REG_STOP_RTC_M, |
165 | BIT_RTC_CTRL_REG_STOP_RTC_M); | |
166 | if (ret) { | |
167 | dev_err(dev, "Failed to update RTC control: %d\n", ret); | |
168 | return ret; | |
169 | } | |
170 | ||
2e830ccc | 171 | ret = regmap_bulk_write(rk808_rtc->regmap, rk808_rtc->creg->seconds_reg, |
3ca1e326 CZ |
172 | rtc_data, NUM_TIME_REGS); |
173 | if (ret) { | |
174 | dev_err(dev, "Failed to bull write rtc_data: %d\n", ret); | |
175 | return ret; | |
176 | } | |
177 | /* Start RTC again */ | |
2e830ccc | 178 | ret = regmap_update_bits(rk808_rtc->regmap, rk808_rtc->creg->ctrl_reg, |
3ca1e326 CZ |
179 | BIT_RTC_CTRL_REG_STOP_RTC_M, 0); |
180 | if (ret) { | |
181 | dev_err(dev, "Failed to update RTC control: %d\n", ret); | |
182 | return ret; | |
183 | } | |
184 | return 0; | |
185 | } | |
186 | ||
187 | /* Read alarm time and date in RTC */ | |
188 | static int rk808_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) | |
189 | { | |
190 | struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev); | |
3ca1e326 CZ |
191 | u8 alrm_data[NUM_ALARM_REGS]; |
192 | uint32_t int_reg; | |
193 | int ret; | |
194 | ||
2e830ccc | 195 | ret = regmap_bulk_read(rk808_rtc->regmap, |
dc79054a | 196 | rk808_rtc->creg->alarm_seconds_reg, |
3ca1e326 | 197 | alrm_data, NUM_ALARM_REGS); |
dc79054a TX |
198 | if (ret) { |
199 | dev_err(dev, "Failed to read RTC alarm date REG: %d\n", ret); | |
200 | return ret; | |
201 | } | |
3ca1e326 CZ |
202 | |
203 | alrm->time.tm_sec = bcd2bin(alrm_data[0] & SECONDS_REG_MSK); | |
204 | alrm->time.tm_min = bcd2bin(alrm_data[1] & MINUTES_REG_MAK); | |
205 | alrm->time.tm_hour = bcd2bin(alrm_data[2] & HOURS_REG_MSK); | |
206 | alrm->time.tm_mday = bcd2bin(alrm_data[3] & DAYS_REG_MSK); | |
207 | alrm->time.tm_mon = (bcd2bin(alrm_data[4] & MONTHS_REG_MSK)) - 1; | |
208 | alrm->time.tm_year = (bcd2bin(alrm_data[5] & YEARS_REG_MSK)) + 100; | |
f076ef44 | 209 | rockchip_to_gregorian(&alrm->time); |
3ca1e326 | 210 | |
2e830ccc | 211 | ret = regmap_read(rk808_rtc->regmap, rk808_rtc->creg->int_reg, &int_reg); |
3ca1e326 CZ |
212 | if (ret) { |
213 | dev_err(dev, "Failed to read RTC INT REG: %d\n", ret); | |
214 | return ret; | |
215 | } | |
216 | ||
0991e754 AS |
217 | dev_dbg(dev, "alrm read RTC date/time %ptRd(%d) %ptRt\n", |
218 | &alrm->time, alrm->time.tm_wday, &alrm->time); | |
3ca1e326 CZ |
219 | |
220 | alrm->enabled = (int_reg & BIT_RTC_INTERRUPTS_REG_IT_ALARM_M) ? 1 : 0; | |
221 | ||
222 | return 0; | |
223 | } | |
224 | ||
225 | static int rk808_rtc_stop_alarm(struct rk808_rtc *rk808_rtc) | |
226 | { | |
3ca1e326 CZ |
227 | int ret; |
228 | ||
2e830ccc | 229 | ret = regmap_update_bits(rk808_rtc->regmap, rk808_rtc->creg->int_reg, |
3ca1e326 CZ |
230 | BIT_RTC_INTERRUPTS_REG_IT_ALARM_M, 0); |
231 | ||
232 | return ret; | |
233 | } | |
234 | ||
235 | static int rk808_rtc_start_alarm(struct rk808_rtc *rk808_rtc) | |
236 | { | |
3ca1e326 CZ |
237 | int ret; |
238 | ||
2e830ccc | 239 | ret = regmap_update_bits(rk808_rtc->regmap, rk808_rtc->creg->int_reg, |
3ca1e326 CZ |
240 | BIT_RTC_INTERRUPTS_REG_IT_ALARM_M, |
241 | BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); | |
242 | ||
243 | return ret; | |
244 | } | |
245 | ||
246 | static int rk808_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |
247 | { | |
248 | struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev); | |
3ca1e326 CZ |
249 | u8 alrm_data[NUM_ALARM_REGS]; |
250 | int ret; | |
251 | ||
252 | ret = rk808_rtc_stop_alarm(rk808_rtc); | |
253 | if (ret) { | |
254 | dev_err(dev, "Failed to stop alarm: %d\n", ret); | |
255 | return ret; | |
256 | } | |
0991e754 AS |
257 | dev_dbg(dev, "alrm set RTC date/time %ptRd(%d) %ptRt\n", |
258 | &alrm->time, alrm->time.tm_wday, &alrm->time); | |
3ca1e326 | 259 | |
f076ef44 | 260 | gregorian_to_rockchip(&alrm->time); |
3ca1e326 CZ |
261 | alrm_data[0] = bin2bcd(alrm->time.tm_sec); |
262 | alrm_data[1] = bin2bcd(alrm->time.tm_min); | |
263 | alrm_data[2] = bin2bcd(alrm->time.tm_hour); | |
264 | alrm_data[3] = bin2bcd(alrm->time.tm_mday); | |
265 | alrm_data[4] = bin2bcd(alrm->time.tm_mon + 1); | |
266 | alrm_data[5] = bin2bcd(alrm->time.tm_year - 100); | |
267 | ||
2e830ccc | 268 | ret = regmap_bulk_write(rk808_rtc->regmap, |
dc79054a | 269 | rk808_rtc->creg->alarm_seconds_reg, |
3ca1e326 CZ |
270 | alrm_data, NUM_ALARM_REGS); |
271 | if (ret) { | |
272 | dev_err(dev, "Failed to bulk write: %d\n", ret); | |
273 | return ret; | |
274 | } | |
275 | if (alrm->enabled) { | |
276 | ret = rk808_rtc_start_alarm(rk808_rtc); | |
277 | if (ret) { | |
278 | dev_err(dev, "Failed to start alarm: %d\n", ret); | |
279 | return ret; | |
280 | } | |
281 | } | |
282 | return 0; | |
283 | } | |
284 | ||
285 | static int rk808_rtc_alarm_irq_enable(struct device *dev, | |
286 | unsigned int enabled) | |
287 | { | |
288 | struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev); | |
289 | ||
290 | if (enabled) | |
291 | return rk808_rtc_start_alarm(rk808_rtc); | |
292 | ||
293 | return rk808_rtc_stop_alarm(rk808_rtc); | |
294 | } | |
295 | ||
296 | /* | |
297 | * We will just handle setting the frequency and make use the framework for | |
298 | * reading the periodic interupts. | |
299 | * | |
300 | * @freq: Current periodic IRQ freq: | |
301 | * bit 0: every second | |
302 | * bit 1: every minute | |
303 | * bit 2: every hour | |
304 | * bit 3: every day | |
305 | */ | |
306 | static irqreturn_t rk808_alarm_irq(int irq, void *data) | |
307 | { | |
308 | struct rk808_rtc *rk808_rtc = data; | |
3ca1e326 CZ |
309 | int ret; |
310 | ||
2e830ccc | 311 | ret = regmap_write(rk808_rtc->regmap, rk808_rtc->creg->status_reg, |
3ca1e326 CZ |
312 | RTC_STATUS_MASK); |
313 | if (ret) { | |
2e830ccc | 314 | dev_err(&rk808_rtc->rtc->dev, |
3ca1e326 CZ |
315 | "%s:Failed to update RTC status: %d\n", __func__, ret); |
316 | return ret; | |
317 | } | |
318 | ||
319 | rtc_update_irq(rk808_rtc->rtc, 1, RTC_IRQF | RTC_AF); | |
2e830ccc | 320 | dev_dbg(&rk808_rtc->rtc->dev, |
3ca1e326 CZ |
321 | "%s:irq=%d\n", __func__, irq); |
322 | return IRQ_HANDLED; | |
323 | } | |
324 | ||
325 | static const struct rtc_class_ops rk808_rtc_ops = { | |
326 | .read_time = rk808_rtc_readtime, | |
327 | .set_time = rk808_rtc_set_time, | |
328 | .read_alarm = rk808_rtc_readalarm, | |
329 | .set_alarm = rk808_rtc_setalarm, | |
330 | .alarm_irq_enable = rk808_rtc_alarm_irq_enable, | |
331 | }; | |
332 | ||
333 | #ifdef CONFIG_PM_SLEEP | |
334 | /* Turn off the alarm if it should not be a wake source. */ | |
335 | static int rk808_rtc_suspend(struct device *dev) | |
336 | { | |
527bd754 | 337 | struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev); |
3ca1e326 CZ |
338 | |
339 | if (device_may_wakeup(dev)) | |
340 | enable_irq_wake(rk808_rtc->irq); | |
341 | ||
342 | return 0; | |
343 | } | |
344 | ||
345 | /* Enable the alarm if it should be enabled (in case it was disabled to | |
346 | * prevent use as a wake source). | |
347 | */ | |
348 | static int rk808_rtc_resume(struct device *dev) | |
349 | { | |
527bd754 | 350 | struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev); |
3ca1e326 CZ |
351 | |
352 | if (device_may_wakeup(dev)) | |
353 | disable_irq_wake(rk808_rtc->irq); | |
354 | ||
355 | return 0; | |
356 | } | |
357 | #endif | |
358 | ||
359 | static SIMPLE_DEV_PM_OPS(rk808_rtc_pm_ops, | |
360 | rk808_rtc_suspend, rk808_rtc_resume); | |
361 | ||
dc79054a TX |
362 | static struct rk_rtc_compat_reg rk808_creg = { |
363 | .ctrl_reg = RK808_RTC_CTRL_REG, | |
364 | .status_reg = RK808_RTC_STATUS_REG, | |
365 | .alarm_seconds_reg = RK808_ALARM_SECONDS_REG, | |
366 | .int_reg = RK808_RTC_INT_REG, | |
367 | .seconds_reg = RK808_SECONDS_REG, | |
368 | }; | |
369 | ||
370 | static struct rk_rtc_compat_reg rk817_creg = { | |
371 | .ctrl_reg = RK817_RTC_CTRL_REG, | |
372 | .status_reg = RK817_RTC_STATUS_REG, | |
373 | .alarm_seconds_reg = RK817_ALARM_SECONDS_REG, | |
374 | .int_reg = RK817_RTC_INT_REG, | |
375 | .seconds_reg = RK817_SECONDS_REG, | |
376 | }; | |
377 | ||
3ca1e326 CZ |
378 | static int rk808_rtc_probe(struct platform_device *pdev) |
379 | { | |
380 | struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent); | |
381 | struct rk808_rtc *rk808_rtc; | |
3ca1e326 CZ |
382 | int ret; |
383 | ||
384 | rk808_rtc = devm_kzalloc(&pdev->dev, sizeof(*rk808_rtc), GFP_KERNEL); | |
385 | if (rk808_rtc == NULL) | |
386 | return -ENOMEM; | |
387 | ||
dc79054a TX |
388 | switch (rk808->variant) { |
389 | case RK809_ID: | |
390 | case RK817_ID: | |
391 | rk808_rtc->creg = &rk817_creg; | |
392 | break; | |
393 | default: | |
394 | rk808_rtc->creg = &rk808_creg; | |
395 | break; | |
396 | } | |
3ca1e326 | 397 | platform_set_drvdata(pdev, rk808_rtc); |
2e830ccc SR |
398 | rk808_rtc->regmap = dev_get_regmap(pdev->dev.parent, NULL); |
399 | if (!rk808_rtc->regmap) | |
400 | return -ENODEV; | |
3ca1e326 CZ |
401 | |
402 | /* start rtc running by default, and use shadowed timer. */ | |
2e830ccc | 403 | ret = regmap_update_bits(rk808_rtc->regmap, rk808_rtc->creg->ctrl_reg, |
3ca1e326 CZ |
404 | BIT_RTC_CTRL_REG_STOP_RTC_M | |
405 | BIT_RTC_CTRL_REG_RTC_READSEL_M, | |
406 | BIT_RTC_CTRL_REG_RTC_READSEL_M); | |
407 | if (ret) { | |
408 | dev_err(&pdev->dev, | |
409 | "Failed to update RTC control: %d\n", ret); | |
410 | return ret; | |
411 | } | |
412 | ||
2e830ccc | 413 | ret = regmap_write(rk808_rtc->regmap, rk808_rtc->creg->status_reg, |
3ca1e326 CZ |
414 | RTC_STATUS_MASK); |
415 | if (ret) { | |
416 | dev_err(&pdev->dev, | |
417 | "Failed to write RTC status: %d\n", ret); | |
725412d9 | 418 | return ret; |
3ca1e326 CZ |
419 | } |
420 | ||
3ca1e326 CZ |
421 | device_init_wakeup(&pdev->dev, 1); |
422 | ||
201fac95 AB |
423 | rk808_rtc->rtc = devm_rtc_allocate_device(&pdev->dev); |
424 | if (IS_ERR(rk808_rtc->rtc)) | |
425 | return PTR_ERR(rk808_rtc->rtc); | |
426 | ||
427 | rk808_rtc->rtc->ops = &rk808_rtc_ops; | |
3ca1e326 CZ |
428 | |
429 | rk808_rtc->irq = platform_get_irq(pdev, 0); | |
faac9102 | 430 | if (rk808_rtc->irq < 0) |
3ca1e326 | 431 | return rk808_rtc->irq; |
3ca1e326 CZ |
432 | |
433 | /* request alarm irq of rk808 */ | |
434 | ret = devm_request_threaded_irq(&pdev->dev, rk808_rtc->irq, NULL, | |
435 | rk808_alarm_irq, 0, | |
436 | "RTC alarm", rk808_rtc); | |
437 | if (ret) { | |
438 | dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n", | |
439 | rk808_rtc->irq, ret); | |
201fac95 | 440 | return ret; |
3ca1e326 CZ |
441 | } |
442 | ||
fdcfd854 | 443 | return devm_rtc_register_device(rk808_rtc->rtc); |
3ca1e326 CZ |
444 | } |
445 | ||
446 | static struct platform_driver rk808_rtc_driver = { | |
447 | .probe = rk808_rtc_probe, | |
448 | .driver = { | |
449 | .name = "rk808-rtc", | |
450 | .pm = &rk808_rtc_pm_ops, | |
451 | }, | |
452 | }; | |
453 | ||
454 | module_platform_driver(rk808_rtc_driver); | |
455 | ||
456 | MODULE_DESCRIPTION("RTC driver for the rk808 series PMICs"); | |
457 | MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>"); | |
458 | MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>"); | |
459 | MODULE_LICENSE("GPL"); | |
460 | MODULE_ALIAS("platform:rk808-rtc"); |