Commit | Line | Data |
---|---|---|
a636cd6c | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
e88b815e XD |
2 | /* |
3 | * SiRFSoC Real Time Clock interface for Linux | |
4 | * | |
5 | * Copyright (c) 2013 Cambridge Silicon Radio Limited, a CSR plc group company. | |
e88b815e XD |
6 | */ |
7 | ||
8 | #include <linux/module.h> | |
9 | #include <linux/err.h> | |
10 | #include <linux/rtc.h> | |
11 | #include <linux/platform_device.h> | |
12 | #include <linux/slab.h> | |
13 | #include <linux/io.h> | |
14 | #include <linux/of.h> | |
dfe6c04a | 15 | #include <linux/regmap.h> |
e88b815e XD |
16 | #include <linux/rtc/sirfsoc_rtciobrg.h> |
17 | ||
18 | ||
19 | #define RTC_CN 0x00 | |
20 | #define RTC_ALARM0 0x04 | |
21 | #define RTC_ALARM1 0x18 | |
22 | #define RTC_STATUS 0x08 | |
23 | #define RTC_SW_VALUE 0x40 | |
24 | #define SIRFSOC_RTC_AL1E (1<<6) | |
25 | #define SIRFSOC_RTC_AL1 (1<<4) | |
26 | #define SIRFSOC_RTC_HZE (1<<3) | |
27 | #define SIRFSOC_RTC_AL0E (1<<2) | |
28 | #define SIRFSOC_RTC_HZ (1<<1) | |
29 | #define SIRFSOC_RTC_AL0 (1<<0) | |
30 | #define RTC_DIV 0x0c | |
31 | #define RTC_DEEP_CTRL 0x14 | |
32 | #define RTC_CLOCK_SWITCH 0x1c | |
33 | #define SIRFSOC_RTC_CLK 0x03 /* others are reserved */ | |
34 | ||
35 | /* Refer to RTC DIV switch */ | |
36 | #define RTC_HZ 16 | |
37 | ||
38 | /* This macro is also defined in arch/arm/plat-sirfsoc/cpu.c */ | |
39 | #define RTC_SHIFT 4 | |
40 | ||
41 | #define INTR_SYSRTC_CN 0x48 | |
42 | ||
43 | struct sirfsoc_rtc_drv { | |
44 | struct rtc_device *rtc; | |
45 | u32 rtc_base; | |
46 | u32 irq; | |
28984c7d | 47 | unsigned irq_wake; |
e88b815e XD |
48 | /* Overflow for every 8 years extra time */ |
49 | u32 overflow_rtc; | |
e9bc7363 | 50 | spinlock_t lock; |
dfe6c04a | 51 | struct regmap *regmap; |
e88b815e XD |
52 | #ifdef CONFIG_PM |
53 | u32 saved_counter; | |
54 | u32 saved_overflow_rtc; | |
55 | #endif | |
56 | }; | |
57 | ||
dfe6c04a GZ |
58 | static u32 sirfsoc_rtc_readl(struct sirfsoc_rtc_drv *rtcdrv, u32 offset) |
59 | { | |
60 | u32 val; | |
61 | ||
62 | regmap_read(rtcdrv->regmap, rtcdrv->rtc_base + offset, &val); | |
63 | return val; | |
64 | } | |
65 | ||
66 | static void sirfsoc_rtc_writel(struct sirfsoc_rtc_drv *rtcdrv, | |
67 | u32 offset, u32 val) | |
68 | { | |
69 | regmap_write(rtcdrv->regmap, rtcdrv->rtc_base + offset, val); | |
70 | } | |
71 | ||
e88b815e XD |
72 | static int sirfsoc_rtc_read_alarm(struct device *dev, |
73 | struct rtc_wkalrm *alrm) | |
74 | { | |
75 | unsigned long rtc_alarm, rtc_count; | |
76 | struct sirfsoc_rtc_drv *rtcdrv; | |
77 | ||
b7efdf3b | 78 | rtcdrv = dev_get_drvdata(dev); |
e88b815e | 79 | |
e9bc7363 | 80 | spin_lock_irq(&rtcdrv->lock); |
e88b815e | 81 | |
dfe6c04a | 82 | rtc_count = sirfsoc_rtc_readl(rtcdrv, RTC_CN); |
e88b815e | 83 | |
dfe6c04a | 84 | rtc_alarm = sirfsoc_rtc_readl(rtcdrv, RTC_ALARM0); |
e88b815e XD |
85 | memset(alrm, 0, sizeof(struct rtc_wkalrm)); |
86 | ||
87 | /* | |
88 | * assume alarm interval not beyond one round counter overflow_rtc: | |
89 | * 0->0xffffffff | |
90 | */ | |
91 | /* if alarm is in next overflow cycle */ | |
92 | if (rtc_count > rtc_alarm) | |
09b875a4 AB |
93 | rtc_time64_to_tm((rtcdrv->overflow_rtc + 1) |
94 | << (BITS_PER_LONG - RTC_SHIFT) | |
95 | | rtc_alarm >> RTC_SHIFT, &alrm->time); | |
e88b815e | 96 | else |
09b875a4 AB |
97 | rtc_time64_to_tm(rtcdrv->overflow_rtc |
98 | << (BITS_PER_LONG - RTC_SHIFT) | |
99 | | rtc_alarm >> RTC_SHIFT, &alrm->time); | |
dfe6c04a | 100 | if (sirfsoc_rtc_readl(rtcdrv, RTC_STATUS) & SIRFSOC_RTC_AL0E) |
e88b815e | 101 | alrm->enabled = 1; |
e9bc7363 BS |
102 | |
103 | spin_unlock_irq(&rtcdrv->lock); | |
e88b815e XD |
104 | |
105 | return 0; | |
106 | } | |
107 | ||
108 | static int sirfsoc_rtc_set_alarm(struct device *dev, | |
109 | struct rtc_wkalrm *alrm) | |
110 | { | |
111 | unsigned long rtc_status_reg, rtc_alarm; | |
112 | struct sirfsoc_rtc_drv *rtcdrv; | |
b7efdf3b | 113 | rtcdrv = dev_get_drvdata(dev); |
e88b815e XD |
114 | |
115 | if (alrm->enabled) { | |
09b875a4 | 116 | rtc_alarm = rtc_tm_to_time64(&alrm->time); |
e88b815e | 117 | |
e9bc7363 | 118 | spin_lock_irq(&rtcdrv->lock); |
e88b815e | 119 | |
dfe6c04a | 120 | rtc_status_reg = sirfsoc_rtc_readl(rtcdrv, RTC_STATUS); |
e88b815e XD |
121 | if (rtc_status_reg & SIRFSOC_RTC_AL0E) { |
122 | /* | |
123 | * An ongoing alarm in progress - ingore it and not | |
124 | * to return EBUSY | |
125 | */ | |
126 | dev_info(dev, "An old alarm was set, will be replaced by a new one\n"); | |
127 | } | |
128 | ||
dfe6c04a | 129 | sirfsoc_rtc_writel(rtcdrv, RTC_ALARM0, rtc_alarm << RTC_SHIFT); |
e88b815e XD |
130 | rtc_status_reg &= ~0x07; /* mask out the lower status bits */ |
131 | /* | |
132 | * This bit RTC_AL sets it as a wake-up source for Sleep Mode | |
133 | * Writing 1 into this bit will clear it | |
134 | */ | |
135 | rtc_status_reg |= SIRFSOC_RTC_AL0; | |
136 | /* enable the RTC alarm interrupt */ | |
137 | rtc_status_reg |= SIRFSOC_RTC_AL0E; | |
dfe6c04a | 138 | sirfsoc_rtc_writel(rtcdrv, RTC_STATUS, rtc_status_reg); |
e9bc7363 BS |
139 | |
140 | spin_unlock_irq(&rtcdrv->lock); | |
e88b815e XD |
141 | } else { |
142 | /* | |
143 | * if this function was called with enabled=0 | |
144 | * then it could mean that the application is | |
145 | * trying to cancel an ongoing alarm | |
146 | */ | |
e9bc7363 | 147 | spin_lock_irq(&rtcdrv->lock); |
e88b815e | 148 | |
dfe6c04a | 149 | rtc_status_reg = sirfsoc_rtc_readl(rtcdrv, RTC_STATUS); |
e88b815e XD |
150 | if (rtc_status_reg & SIRFSOC_RTC_AL0E) { |
151 | /* clear the RTC status register's alarm bit */ | |
152 | rtc_status_reg &= ~0x07; | |
153 | /* write 1 into SIRFSOC_RTC_AL0 to force a clear */ | |
154 | rtc_status_reg |= (SIRFSOC_RTC_AL0); | |
155 | /* Clear the Alarm enable bit */ | |
156 | rtc_status_reg &= ~(SIRFSOC_RTC_AL0E); | |
157 | ||
dfe6c04a GZ |
158 | sirfsoc_rtc_writel(rtcdrv, RTC_STATUS, |
159 | rtc_status_reg); | |
e88b815e XD |
160 | } |
161 | ||
e9bc7363 | 162 | spin_unlock_irq(&rtcdrv->lock); |
e88b815e XD |
163 | } |
164 | ||
165 | return 0; | |
166 | } | |
167 | ||
168 | static int sirfsoc_rtc_read_time(struct device *dev, | |
169 | struct rtc_time *tm) | |
170 | { | |
171 | unsigned long tmp_rtc = 0; | |
172 | struct sirfsoc_rtc_drv *rtcdrv; | |
b7efdf3b | 173 | rtcdrv = dev_get_drvdata(dev); |
e88b815e XD |
174 | /* |
175 | * This patch is taken from WinCE - Need to validate this for | |
176 | * correctness. To work around sirfsoc RTC counter double sync logic | |
177 | * fail, read several times to make sure get stable value. | |
178 | */ | |
179 | do { | |
dfe6c04a | 180 | tmp_rtc = sirfsoc_rtc_readl(rtcdrv, RTC_CN); |
e88b815e | 181 | cpu_relax(); |
dfe6c04a | 182 | } while (tmp_rtc != sirfsoc_rtc_readl(rtcdrv, RTC_CN)); |
e88b815e | 183 | |
09b875a4 AB |
184 | rtc_time64_to_tm(rtcdrv->overflow_rtc << (BITS_PER_LONG - RTC_SHIFT) |
185 | | tmp_rtc >> RTC_SHIFT, tm); | |
e88b815e XD |
186 | return 0; |
187 | } | |
188 | ||
189 | static int sirfsoc_rtc_set_time(struct device *dev, | |
190 | struct rtc_time *tm) | |
191 | { | |
192 | unsigned long rtc_time; | |
193 | struct sirfsoc_rtc_drv *rtcdrv; | |
b7efdf3b | 194 | rtcdrv = dev_get_drvdata(dev); |
e88b815e | 195 | |
09b875a4 | 196 | rtc_time = rtc_tm_to_time64(tm); |
e88b815e XD |
197 | |
198 | rtcdrv->overflow_rtc = rtc_time >> (BITS_PER_LONG - RTC_SHIFT); | |
199 | ||
dfe6c04a GZ |
200 | sirfsoc_rtc_writel(rtcdrv, RTC_SW_VALUE, rtcdrv->overflow_rtc); |
201 | sirfsoc_rtc_writel(rtcdrv, RTC_CN, rtc_time << RTC_SHIFT); | |
e88b815e XD |
202 | |
203 | return 0; | |
204 | } | |
205 | ||
09e427f8 | 206 | static int sirfsoc_rtc_alarm_irq_enable(struct device *dev, |
207 | unsigned int enabled) | |
208 | { | |
209 | unsigned long rtc_status_reg = 0x0; | |
210 | struct sirfsoc_rtc_drv *rtcdrv; | |
211 | ||
212 | rtcdrv = dev_get_drvdata(dev); | |
213 | ||
e9bc7363 | 214 | spin_lock_irq(&rtcdrv->lock); |
09e427f8 | 215 | |
dfe6c04a | 216 | rtc_status_reg = sirfsoc_rtc_readl(rtcdrv, RTC_STATUS); |
09e427f8 | 217 | if (enabled) |
218 | rtc_status_reg |= SIRFSOC_RTC_AL0E; | |
219 | else | |
220 | rtc_status_reg &= ~SIRFSOC_RTC_AL0E; | |
221 | ||
dfe6c04a | 222 | sirfsoc_rtc_writel(rtcdrv, RTC_STATUS, rtc_status_reg); |
e9bc7363 BS |
223 | |
224 | spin_unlock_irq(&rtcdrv->lock); | |
09e427f8 | 225 | |
226 | return 0; | |
227 | ||
228 | } | |
229 | ||
e88b815e XD |
230 | static const struct rtc_class_ops sirfsoc_rtc_ops = { |
231 | .read_time = sirfsoc_rtc_read_time, | |
232 | .set_time = sirfsoc_rtc_set_time, | |
233 | .read_alarm = sirfsoc_rtc_read_alarm, | |
234 | .set_alarm = sirfsoc_rtc_set_alarm, | |
09e427f8 | 235 | .alarm_irq_enable = sirfsoc_rtc_alarm_irq_enable |
e88b815e XD |
236 | }; |
237 | ||
238 | static irqreturn_t sirfsoc_rtc_irq_handler(int irq, void *pdata) | |
239 | { | |
240 | struct sirfsoc_rtc_drv *rtcdrv = pdata; | |
241 | unsigned long rtc_status_reg = 0x0; | |
242 | unsigned long events = 0x0; | |
243 | ||
e9bc7363 BS |
244 | spin_lock(&rtcdrv->lock); |
245 | ||
dfe6c04a | 246 | rtc_status_reg = sirfsoc_rtc_readl(rtcdrv, RTC_STATUS); |
e88b815e XD |
247 | /* this bit will be set ONLY if an alarm was active |
248 | * and it expired NOW | |
249 | * So this is being used as an ASSERT | |
250 | */ | |
251 | if (rtc_status_reg & SIRFSOC_RTC_AL0) { | |
252 | /* | |
253 | * clear the RTC status register's alarm bit | |
254 | * mask out the lower status bits | |
255 | */ | |
256 | rtc_status_reg &= ~0x07; | |
257 | /* write 1 into SIRFSOC_RTC_AL0 to ACK the alarm interrupt */ | |
258 | rtc_status_reg |= (SIRFSOC_RTC_AL0); | |
259 | /* Clear the Alarm enable bit */ | |
260 | rtc_status_reg &= ~(SIRFSOC_RTC_AL0E); | |
261 | } | |
dfe6c04a GZ |
262 | |
263 | sirfsoc_rtc_writel(rtcdrv, RTC_STATUS, rtc_status_reg); | |
e9bc7363 BS |
264 | |
265 | spin_unlock(&rtcdrv->lock); | |
266 | ||
e88b815e XD |
267 | /* this should wake up any apps polling/waiting on the read |
268 | * after setting the alarm | |
269 | */ | |
270 | events |= RTC_IRQF | RTC_AF; | |
271 | rtc_update_irq(rtcdrv->rtc, 1, events); | |
272 | ||
273 | return IRQ_HANDLED; | |
274 | } | |
275 | ||
276 | static const struct of_device_id sirfsoc_rtc_of_match[] = { | |
277 | { .compatible = "sirf,prima2-sysrtc"}, | |
278 | {}, | |
279 | }; | |
dfe6c04a | 280 | |
153a9177 | 281 | static const struct regmap_config sysrtc_regmap_config = { |
dfe6c04a GZ |
282 | .reg_bits = 32, |
283 | .val_bits = 32, | |
284 | .fast_io = true, | |
285 | }; | |
286 | ||
e88b815e XD |
287 | MODULE_DEVICE_TABLE(of, sirfsoc_rtc_of_match); |
288 | ||
289 | static int sirfsoc_rtc_probe(struct platform_device *pdev) | |
290 | { | |
291 | int err; | |
292 | unsigned long rtc_div; | |
293 | struct sirfsoc_rtc_drv *rtcdrv; | |
294 | struct device_node *np = pdev->dev.of_node; | |
295 | ||
296 | rtcdrv = devm_kzalloc(&pdev->dev, | |
297 | sizeof(struct sirfsoc_rtc_drv), GFP_KERNEL); | |
98e2d21f | 298 | if (rtcdrv == NULL) |
e88b815e | 299 | return -ENOMEM; |
e88b815e | 300 | |
e9bc7363 BS |
301 | spin_lock_init(&rtcdrv->lock); |
302 | ||
e88b815e XD |
303 | err = of_property_read_u32(np, "reg", &rtcdrv->rtc_base); |
304 | if (err) { | |
305 | dev_err(&pdev->dev, "unable to find base address of rtc node in dtb\n"); | |
3d09162e | 306 | return err; |
e88b815e XD |
307 | } |
308 | ||
309 | platform_set_drvdata(pdev, rtcdrv); | |
310 | ||
311 | /* Register rtc alarm as a wakeup source */ | |
312 | device_init_wakeup(&pdev->dev, 1); | |
313 | ||
dfe6c04a GZ |
314 | rtcdrv->regmap = devm_regmap_init_iobg(&pdev->dev, |
315 | &sysrtc_regmap_config); | |
316 | if (IS_ERR(rtcdrv->regmap)) { | |
317 | err = PTR_ERR(rtcdrv->regmap); | |
318 | dev_err(&pdev->dev, "Failed to allocate register map: %d\n", | |
319 | err); | |
320 | return err; | |
321 | } | |
322 | ||
e88b815e XD |
323 | /* |
324 | * Set SYS_RTC counter in RTC_HZ HZ Units | |
325 | * We are using 32K RTC crystal (32768 / RTC_HZ / 2) -1 | |
326 | * If 16HZ, therefore RTC_DIV = 1023; | |
327 | */ | |
328 | rtc_div = ((32768 / RTC_HZ) / 2) - 1; | |
dfe6c04a | 329 | sirfsoc_rtc_writel(rtcdrv, RTC_DIV, rtc_div); |
e88b815e | 330 | |
e88b815e | 331 | /* 0x3 -> RTC_CLK */ |
dfe6c04a | 332 | sirfsoc_rtc_writel(rtcdrv, RTC_CLOCK_SWITCH, SIRFSOC_RTC_CLK); |
e88b815e XD |
333 | |
334 | /* reset SYS RTC ALARM0 */ | |
dfe6c04a | 335 | sirfsoc_rtc_writel(rtcdrv, RTC_ALARM0, 0x0); |
e88b815e XD |
336 | |
337 | /* reset SYS RTC ALARM1 */ | |
dfe6c04a | 338 | sirfsoc_rtc_writel(rtcdrv, RTC_ALARM1, 0x0); |
e88b815e XD |
339 | |
340 | /* Restore RTC Overflow From Register After Command Reboot */ | |
341 | rtcdrv->overflow_rtc = | |
dfe6c04a | 342 | sirfsoc_rtc_readl(rtcdrv, RTC_SW_VALUE); |
e88b815e | 343 | |
2911ee9e AB |
344 | rtcdrv->rtc = devm_rtc_allocate_device(&pdev->dev); |
345 | if (IS_ERR(rtcdrv->rtc)) | |
346 | return PTR_ERR(rtcdrv->rtc); | |
347 | ||
348 | rtcdrv->rtc->ops = &sirfsoc_rtc_ops; | |
cd65dd41 | 349 | rtcdrv->rtc->range_max = (1ULL << 60) - 1; |
0e953255 | 350 | |
e88b815e | 351 | rtcdrv->irq = platform_get_irq(pdev, 0); |
2911ee9e AB |
352 | err = devm_request_irq(&pdev->dev, rtcdrv->irq, sirfsoc_rtc_irq_handler, |
353 | IRQF_SHARED, pdev->name, rtcdrv); | |
e88b815e XD |
354 | if (err) { |
355 | dev_err(&pdev->dev, "Unable to register for the SiRF SOC RTC IRQ\n"); | |
3d09162e | 356 | return err; |
e88b815e XD |
357 | } |
358 | ||
2911ee9e | 359 | return rtc_register_device(rtcdrv->rtc); |
e88b815e XD |
360 | } |
361 | ||
3916b09e | 362 | #ifdef CONFIG_PM_SLEEP |
e88b815e XD |
363 | static int sirfsoc_rtc_suspend(struct device *dev) |
364 | { | |
3916b09e | 365 | struct sirfsoc_rtc_drv *rtcdrv = dev_get_drvdata(dev); |
e88b815e | 366 | rtcdrv->overflow_rtc = |
dfe6c04a | 367 | sirfsoc_rtc_readl(rtcdrv, RTC_SW_VALUE); |
e88b815e XD |
368 | |
369 | rtcdrv->saved_counter = | |
dfe6c04a | 370 | sirfsoc_rtc_readl(rtcdrv, RTC_CN); |
e88b815e | 371 | rtcdrv->saved_overflow_rtc = rtcdrv->overflow_rtc; |
3916b09e | 372 | if (device_may_wakeup(dev) && !enable_irq_wake(rtcdrv->irq)) |
28984c7d | 373 | rtcdrv->irq_wake = 1; |
e88b815e XD |
374 | |
375 | return 0; | |
376 | } | |
377 | ||
3916b09e | 378 | static int sirfsoc_rtc_resume(struct device *dev) |
e88b815e XD |
379 | { |
380 | u32 tmp; | |
3916b09e | 381 | struct sirfsoc_rtc_drv *rtcdrv = dev_get_drvdata(dev); |
e88b815e XD |
382 | |
383 | /* | |
3916b09e | 384 | * if resume from snapshot and the rtc power is lost, |
e88b815e XD |
385 | * restroe the rtc settings |
386 | */ | |
dfe6c04a | 387 | if (SIRFSOC_RTC_CLK != sirfsoc_rtc_readl(rtcdrv, RTC_CLOCK_SWITCH)) { |
e88b815e XD |
388 | u32 rtc_div; |
389 | /* 0x3 -> RTC_CLK */ | |
dfe6c04a | 390 | sirfsoc_rtc_writel(rtcdrv, RTC_CLOCK_SWITCH, SIRFSOC_RTC_CLK); |
e88b815e XD |
391 | /* |
392 | * Set SYS_RTC counter in RTC_HZ HZ Units | |
393 | * We are using 32K RTC crystal (32768 / RTC_HZ / 2) -1 | |
394 | * If 16HZ, therefore RTC_DIV = 1023; | |
395 | */ | |
396 | rtc_div = ((32768 / RTC_HZ) / 2) - 1; | |
397 | ||
dfe6c04a | 398 | sirfsoc_rtc_writel(rtcdrv, RTC_DIV, rtc_div); |
e88b815e XD |
399 | |
400 | /* reset SYS RTC ALARM0 */ | |
dfe6c04a | 401 | sirfsoc_rtc_writel(rtcdrv, RTC_ALARM0, 0x0); |
e88b815e XD |
402 | |
403 | /* reset SYS RTC ALARM1 */ | |
dfe6c04a | 404 | sirfsoc_rtc_writel(rtcdrv, RTC_ALARM1, 0x0); |
e88b815e XD |
405 | } |
406 | rtcdrv->overflow_rtc = rtcdrv->saved_overflow_rtc; | |
407 | ||
408 | /* | |
409 | * if current counter is small than previous, | |
410 | * it means overflow in sleep | |
411 | */ | |
dfe6c04a | 412 | tmp = sirfsoc_rtc_readl(rtcdrv, RTC_CN); |
e88b815e XD |
413 | if (tmp <= rtcdrv->saved_counter) |
414 | rtcdrv->overflow_rtc++; | |
415 | /* | |
416 | *PWRC Value Be Changed When Suspend, Restore Overflow | |
417 | * In Memory To Register | |
418 | */ | |
dfe6c04a | 419 | sirfsoc_rtc_writel(rtcdrv, RTC_SW_VALUE, rtcdrv->overflow_rtc); |
e88b815e | 420 | |
3916b09e | 421 | if (device_may_wakeup(dev) && rtcdrv->irq_wake) { |
e88b815e | 422 | disable_irq_wake(rtcdrv->irq); |
28984c7d XD |
423 | rtcdrv->irq_wake = 0; |
424 | } | |
e88b815e XD |
425 | |
426 | return 0; | |
427 | } | |
e88b815e XD |
428 | #endif |
429 | ||
3916b09e XD |
430 | static SIMPLE_DEV_PM_OPS(sirfsoc_rtc_pm_ops, |
431 | sirfsoc_rtc_suspend, sirfsoc_rtc_resume); | |
e88b815e XD |
432 | |
433 | static struct platform_driver sirfsoc_rtc_driver = { | |
434 | .driver = { | |
435 | .name = "sirfsoc-rtc", | |
e88b815e | 436 | .pm = &sirfsoc_rtc_pm_ops, |
d149632e | 437 | .of_match_table = sirfsoc_rtc_of_match, |
e88b815e XD |
438 | }, |
439 | .probe = sirfsoc_rtc_probe, | |
e88b815e XD |
440 | }; |
441 | module_platform_driver(sirfsoc_rtc_driver); | |
442 | ||
443 | MODULE_DESCRIPTION("SiRF SoC rtc driver"); | |
444 | MODULE_AUTHOR("Xianglong Du <Xianglong.Du@csr.com>"); | |
445 | MODULE_LICENSE("GPL v2"); | |
446 | MODULE_ALIAS("platform:sirfsoc-rtc"); |