Root/
1 | /* |
2 | * rtc-tps65910.c -- TPS65910 Real Time Clock interface |
3 | * |
4 | * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. |
5 | * Author: Venu Byravarasu <vbyravarasu@nvidia.com> |
6 | * |
7 | * Based on original TI driver rtc-twl.c |
8 | * Copyright (C) 2007 MontaVista Software, Inc |
9 | * Author: Alexandre Rusev <source@mvista.com> |
10 | * |
11 | * This program is free software; you can redistribute it and/or |
12 | * modify it under the terms of the GNU General Public License |
13 | * as published by the Free Software Foundation; either version |
14 | * 2 of the License, or (at your option) any later version. |
15 | */ |
16 | |
17 | #include <linux/kernel.h> |
18 | #include <linux/errno.h> |
19 | #include <linux/init.h> |
20 | #include <linux/module.h> |
21 | #include <linux/types.h> |
22 | #include <linux/rtc.h> |
23 | #include <linux/bcd.h> |
24 | #include <linux/platform_device.h> |
25 | #include <linux/pm_runtime.h> |
26 | #include <linux/interrupt.h> |
27 | #include <linux/mfd/tps65910.h> |
28 | |
29 | struct tps65910_rtc { |
30 | struct rtc_device *rtc; |
31 | int irq; |
32 | }; |
33 | |
34 | /* Total number of RTC registers needed to set time*/ |
35 | #define NUM_TIME_REGS (TPS65910_YEARS - TPS65910_SECONDS + 1) |
36 | |
37 | static int tps65910_rtc_alarm_irq_enable(struct device *dev, unsigned enabled) |
38 | { |
39 | struct tps65910 *tps = dev_get_drvdata(dev->parent); |
40 | u8 val = 0; |
41 | |
42 | if (enabled) |
43 | val = TPS65910_RTC_INTERRUPTS_IT_ALARM; |
44 | |
45 | return regmap_write(tps->regmap, TPS65910_RTC_INTERRUPTS, val); |
46 | } |
47 | |
48 | /* |
49 | * Gets current tps65910 RTC time and date parameters. |
50 | * |
51 | * The RTC's time/alarm representation is not what gmtime(3) requires |
52 | * Linux to use: |
53 | * |
54 | * - Months are 1..12 vs Linux 0-11 |
55 | * - Years are 0..99 vs Linux 1900..N (we assume 21st century) |
56 | */ |
57 | static int tps65910_rtc_read_time(struct device *dev, struct rtc_time *tm) |
58 | { |
59 | unsigned char rtc_data[NUM_TIME_REGS]; |
60 | struct tps65910 *tps = dev_get_drvdata(dev->parent); |
61 | int ret; |
62 | |
63 | /* Copy RTC counting registers to static registers or latches */ |
64 | ret = regmap_update_bits(tps->regmap, TPS65910_RTC_CTRL, |
65 | TPS65910_RTC_CTRL_GET_TIME, TPS65910_RTC_CTRL_GET_TIME); |
66 | if (ret < 0) { |
67 | dev_err(dev, "RTC CTRL reg update failed with err:%d\n", ret); |
68 | return ret; |
69 | } |
70 | |
71 | ret = regmap_bulk_read(tps->regmap, TPS65910_SECONDS, rtc_data, |
72 | NUM_TIME_REGS); |
73 | if (ret < 0) { |
74 | dev_err(dev, "reading from RTC failed with err:%d\n", ret); |
75 | return ret; |
76 | } |
77 | |
78 | tm->tm_sec = bcd2bin(rtc_data[0]); |
79 | tm->tm_min = bcd2bin(rtc_data[1]); |
80 | tm->tm_hour = bcd2bin(rtc_data[2]); |
81 | tm->tm_mday = bcd2bin(rtc_data[3]); |
82 | tm->tm_mon = bcd2bin(rtc_data[4]) - 1; |
83 | tm->tm_year = bcd2bin(rtc_data[5]) + 100; |
84 | |
85 | return ret; |
86 | } |
87 | |
88 | static int tps65910_rtc_set_time(struct device *dev, struct rtc_time *tm) |
89 | { |
90 | unsigned char rtc_data[NUM_TIME_REGS]; |
91 | struct tps65910 *tps = dev_get_drvdata(dev->parent); |
92 | int ret; |
93 | |
94 | rtc_data[0] = bin2bcd(tm->tm_sec); |
95 | rtc_data[1] = bin2bcd(tm->tm_min); |
96 | rtc_data[2] = bin2bcd(tm->tm_hour); |
97 | rtc_data[3] = bin2bcd(tm->tm_mday); |
98 | rtc_data[4] = bin2bcd(tm->tm_mon + 1); |
99 | rtc_data[5] = bin2bcd(tm->tm_year - 100); |
100 | |
101 | /* Stop RTC while updating the RTC time registers */ |
102 | ret = regmap_update_bits(tps->regmap, TPS65910_RTC_CTRL, |
103 | TPS65910_RTC_CTRL_STOP_RTC, 0); |
104 | if (ret < 0) { |
105 | dev_err(dev, "RTC stop failed with err:%d\n", ret); |
106 | return ret; |
107 | } |
108 | |
109 | /* update all the time registers in one shot */ |
110 | ret = regmap_bulk_write(tps->regmap, TPS65910_SECONDS, rtc_data, |
111 | NUM_TIME_REGS); |
112 | if (ret < 0) { |
113 | dev_err(dev, "rtc_set_time error %d\n", ret); |
114 | return ret; |
115 | } |
116 | |
117 | /* Start back RTC */ |
118 | ret = regmap_update_bits(tps->regmap, TPS65910_RTC_CTRL, |
119 | TPS65910_RTC_CTRL_STOP_RTC, 1); |
120 | if (ret < 0) |
121 | dev_err(dev, "RTC start failed with err:%d\n", ret); |
122 | |
123 | return ret; |
124 | } |
125 | |
126 | /* |
127 | * Gets current tps65910 RTC alarm time. |
128 | */ |
129 | static int tps65910_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) |
130 | { |
131 | unsigned char alarm_data[NUM_TIME_REGS]; |
132 | u32 int_val; |
133 | struct tps65910 *tps = dev_get_drvdata(dev->parent); |
134 | int ret; |
135 | |
136 | ret = regmap_bulk_read(tps->regmap, TPS65910_SECONDS, alarm_data, |
137 | NUM_TIME_REGS); |
138 | if (ret < 0) { |
139 | dev_err(dev, "rtc_read_alarm error %d\n", ret); |
140 | return ret; |
141 | } |
142 | |
143 | alm->time.tm_sec = bcd2bin(alarm_data[0]); |
144 | alm->time.tm_min = bcd2bin(alarm_data[1]); |
145 | alm->time.tm_hour = bcd2bin(alarm_data[2]); |
146 | alm->time.tm_mday = bcd2bin(alarm_data[3]); |
147 | alm->time.tm_mon = bcd2bin(alarm_data[4]) - 1; |
148 | alm->time.tm_year = bcd2bin(alarm_data[5]) + 100; |
149 | |
150 | ret = regmap_read(tps->regmap, TPS65910_RTC_INTERRUPTS, &int_val); |
151 | if (ret < 0) |
152 | return ret; |
153 | |
154 | if (int_val & TPS65910_RTC_INTERRUPTS_IT_ALARM) |
155 | alm->enabled = 1; |
156 | |
157 | return ret; |
158 | } |
159 | |
160 | static int tps65910_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) |
161 | { |
162 | unsigned char alarm_data[NUM_TIME_REGS]; |
163 | struct tps65910 *tps = dev_get_drvdata(dev->parent); |
164 | int ret; |
165 | |
166 | ret = tps65910_rtc_alarm_irq_enable(dev, 0); |
167 | if (ret) |
168 | return ret; |
169 | |
170 | alarm_data[0] = bin2bcd(alm->time.tm_sec); |
171 | alarm_data[1] = bin2bcd(alm->time.tm_min); |
172 | alarm_data[2] = bin2bcd(alm->time.tm_hour); |
173 | alarm_data[3] = bin2bcd(alm->time.tm_mday); |
174 | alarm_data[4] = bin2bcd(alm->time.tm_mon + 1); |
175 | alarm_data[5] = bin2bcd(alm->time.tm_year - 100); |
176 | |
177 | /* update all the alarm registers in one shot */ |
178 | ret = regmap_bulk_write(tps->regmap, TPS65910_ALARM_SECONDS, |
179 | alarm_data, NUM_TIME_REGS); |
180 | if (ret) { |
181 | dev_err(dev, "rtc_set_alarm error %d\n", ret); |
182 | return ret; |
183 | } |
184 | |
185 | if (alm->enabled) |
186 | ret = tps65910_rtc_alarm_irq_enable(dev, 1); |
187 | |
188 | return ret; |
189 | } |
190 | |
191 | static irqreturn_t tps65910_rtc_interrupt(int irq, void *rtc) |
192 | { |
193 | struct device *dev = rtc; |
194 | unsigned long events = 0; |
195 | struct tps65910 *tps = dev_get_drvdata(dev->parent); |
196 | struct tps65910_rtc *tps_rtc = dev_get_drvdata(dev); |
197 | int ret; |
198 | u32 rtc_reg; |
199 | |
200 | ret = regmap_read(tps->regmap, TPS65910_RTC_STATUS, &rtc_reg); |
201 | if (ret) |
202 | return IRQ_NONE; |
203 | |
204 | if (rtc_reg & TPS65910_RTC_STATUS_ALARM) |
205 | events = RTC_IRQF | RTC_AF; |
206 | |
207 | ret = regmap_write(tps->regmap, TPS65910_RTC_STATUS, rtc_reg); |
208 | if (ret) |
209 | return IRQ_NONE; |
210 | |
211 | /* Notify RTC core on event */ |
212 | rtc_update_irq(tps_rtc->rtc, 1, events); |
213 | |
214 | return IRQ_HANDLED; |
215 | } |
216 | |
217 | static const struct rtc_class_ops tps65910_rtc_ops = { |
218 | .read_time = tps65910_rtc_read_time, |
219 | .set_time = tps65910_rtc_set_time, |
220 | .read_alarm = tps65910_rtc_read_alarm, |
221 | .set_alarm = tps65910_rtc_set_alarm, |
222 | .alarm_irq_enable = tps65910_rtc_alarm_irq_enable, |
223 | }; |
224 | |
225 | static int tps65910_rtc_probe(struct platform_device *pdev) |
226 | { |
227 | struct tps65910 *tps65910 = NULL; |
228 | struct tps65910_rtc *tps_rtc = NULL; |
229 | int ret; |
230 | int irq; |
231 | u32 rtc_reg; |
232 | |
233 | tps65910 = dev_get_drvdata(pdev->dev.parent); |
234 | |
235 | tps_rtc = devm_kzalloc(&pdev->dev, sizeof(struct tps65910_rtc), |
236 | GFP_KERNEL); |
237 | if (!tps_rtc) |
238 | return -ENOMEM; |
239 | |
240 | /* Clear pending interrupts */ |
241 | ret = regmap_read(tps65910->regmap, TPS65910_RTC_STATUS, &rtc_reg); |
242 | if (ret < 0) |
243 | return ret; |
244 | |
245 | ret = regmap_write(tps65910->regmap, TPS65910_RTC_STATUS, rtc_reg); |
246 | if (ret < 0) |
247 | return ret; |
248 | |
249 | dev_dbg(&pdev->dev, "Enabling rtc-tps65910.\n"); |
250 | |
251 | /* Enable RTC digital power domain */ |
252 | ret = regmap_update_bits(tps65910->regmap, TPS65910_DEVCTRL, |
253 | DEVCTRL_RTC_PWDN_MASK, 0 << DEVCTRL_RTC_PWDN_SHIFT); |
254 | if (ret < 0) |
255 | return ret; |
256 | |
257 | rtc_reg = TPS65910_RTC_CTRL_STOP_RTC; |
258 | ret = regmap_write(tps65910->regmap, TPS65910_RTC_CTRL, rtc_reg); |
259 | if (ret < 0) |
260 | return ret; |
261 | |
262 | irq = platform_get_irq(pdev, 0); |
263 | if (irq <= 0) { |
264 | dev_warn(&pdev->dev, "Wake up is not possible as irq = %d\n", |
265 | irq); |
266 | return ret; |
267 | } |
268 | |
269 | ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, |
270 | tps65910_rtc_interrupt, IRQF_TRIGGER_LOW | IRQF_EARLY_RESUME, |
271 | dev_name(&pdev->dev), &pdev->dev); |
272 | if (ret < 0) { |
273 | dev_err(&pdev->dev, "IRQ is not free.\n"); |
274 | return ret; |
275 | } |
276 | tps_rtc->irq = irq; |
277 | device_set_wakeup_capable(&pdev->dev, 1); |
278 | |
279 | tps_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, |
280 | &tps65910_rtc_ops, THIS_MODULE); |
281 | if (IS_ERR(tps_rtc->rtc)) { |
282 | ret = PTR_ERR(tps_rtc->rtc); |
283 | dev_err(&pdev->dev, "RTC device register: err %d\n", ret); |
284 | return ret; |
285 | } |
286 | |
287 | platform_set_drvdata(pdev, tps_rtc); |
288 | |
289 | return 0; |
290 | } |
291 | |
292 | /* |
293 | * Disable tps65910 RTC interrupts. |
294 | * Sets status flag to free. |
295 | */ |
296 | static int tps65910_rtc_remove(struct platform_device *pdev) |
297 | { |
298 | /* leave rtc running, but disable irqs */ |
299 | struct tps65910_rtc *tps_rtc = platform_get_drvdata(pdev); |
300 | |
301 | tps65910_rtc_alarm_irq_enable(&pdev->dev, 0); |
302 | |
303 | rtc_device_unregister(tps_rtc->rtc); |
304 | return 0; |
305 | } |
306 | |
307 | #ifdef CONFIG_PM_SLEEP |
308 | static int tps65910_rtc_suspend(struct device *dev) |
309 | { |
310 | struct tps65910_rtc *tps_rtc = dev_get_drvdata(dev); |
311 | |
312 | if (device_may_wakeup(dev)) |
313 | enable_irq_wake(tps_rtc->irq); |
314 | return 0; |
315 | } |
316 | |
317 | static int tps65910_rtc_resume(struct device *dev) |
318 | { |
319 | struct tps65910_rtc *tps_rtc = dev_get_drvdata(dev); |
320 | |
321 | if (device_may_wakeup(dev)) |
322 | disable_irq_wake(tps_rtc->irq); |
323 | return 0; |
324 | } |
325 | #endif |
326 | |
327 | static const struct dev_pm_ops tps65910_rtc_pm_ops = { |
328 | SET_SYSTEM_SLEEP_PM_OPS(tps65910_rtc_suspend, tps65910_rtc_resume) |
329 | }; |
330 | |
331 | static struct platform_driver tps65910_rtc_driver = { |
332 | .probe = tps65910_rtc_probe, |
333 | .remove = tps65910_rtc_remove, |
334 | .driver = { |
335 | .owner = THIS_MODULE, |
336 | .name = "tps65910-rtc", |
337 | .pm = &tps65910_rtc_pm_ops, |
338 | }, |
339 | }; |
340 | |
341 | module_platform_driver(tps65910_rtc_driver); |
342 | MODULE_ALIAS("platform:rtc-tps65910"); |
343 | MODULE_AUTHOR("Venu Byravarasu <vbyravarasu@nvidia.com>"); |
344 | MODULE_LICENSE("GPL"); |
345 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9