Date: | 2010-06-28 01:30:56 (13 years 9 months ago) |
---|---|
Author: | Lars C. |
Commit: | 3deecc1845ad830cb640d439b23e78824324e153 |
Message: | RTC: jz4740: Propergate write errors in jz4740_rtc_reg_write up to
its callers |
Files: |
drivers/rtc/rtc-jz4740.c (10 diffs) |
Change Details
drivers/rtc/rtc-jz4740.c | ||
---|---|---|
1 | 1 | /* |
2 | 2 | * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de> |
3 | * JZ4740 SoC RTC driver | |
3 | * JZ4740 SoC RTC driver | |
4 | 4 | * |
5 | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | 6 | * under the terms of the GNU General Public License as published by the |
... | ... | |
51 | 51 | return readl(rtc->base + reg); |
52 | 52 | } |
53 | 53 | |
54 | static inline void jz4740_rtc_wait_write_ready(struct jz4740_rtc *rtc) | |
54 | static int jz4740_rtc_wait_write_ready(struct jz4740_rtc *rtc) | |
55 | 55 | { |
56 | 56 | uint32_t ctrl; |
57 | int timeout = 10; | |
57 | int timeout = 1000; | |
58 | 58 | |
59 | 59 | do { |
60 | 60 | ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL); |
61 | } while (!(ctrl & JZ_RTC_CTRL_WRDY) && timeout--); | |
61 | } while (!(ctrl & JZ_RTC_CTRL_WRDY) && --timeout); | |
62 | ||
63 | return timeout ? 0 : -EIO; | |
62 | 64 | } |
63 | 65 | |
64 | static inline void jz4740_rtc_reg_write(struct jz4740_rtc *rtc, size_t reg, | |
66 | static inline int jz4740_rtc_reg_write(struct jz4740_rtc *rtc, size_t reg, | |
65 | 67 | uint32_t val) |
66 | 68 | { |
67 | jz4740_rtc_wait_write_ready(rtc); | |
68 | writel(val, rtc->base + reg); | |
69 | int ret; | |
70 | ret = jz4740_rtc_wait_write_ready(rtc); | |
71 | if (ret == 0) | |
72 | writel(val, rtc->base + reg); | |
73 | ||
74 | return ret; | |
69 | 75 | } |
70 | 76 | |
71 | static void jz4740_rtc_ctrl_set_bits(struct jz4740_rtc *rtc, uint32_t mask, | |
72 | uint32_t val) | |
77 | static int jz4740_rtc_ctrl_set_bits(struct jz4740_rtc *rtc, uint32_t mask, | |
78 | bool set) | |
73 | 79 | { |
80 | int ret; | |
74 | 81 | unsigned long flags; |
75 | 82 | uint32_t ctrl; |
76 | 83 | |
... | ... | |
81 | 88 | /* Don't clear interrupt flags by accident */ |
82 | 89 | ctrl |= JZ_RTC_CTRL_1HZ | JZ_RTC_CTRL_AF; |
83 | 90 | |
84 | ctrl &= ~mask; | |
85 | ctrl |= val; | |
91 | if (set) | |
92 | ctrl |= mask; | |
93 | else | |
94 | ctrl &= ~mask; | |
86 | 95 | |
87 | jz4740_rtc_reg_write(rtc, JZ_REG_RTC_CTRL, ctrl); | |
96 | ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_CTRL, ctrl); | |
88 | 97 | |
89 | 98 | spin_unlock_irqrestore(&rtc->lock, flags); |
99 | ||
100 | return ret; | |
90 | 101 | } |
91 | 102 | |
92 | 103 | static int jz4740_rtc_read_time(struct device *dev, struct rtc_time *time) |
... | ... | |
102 | 113 | secs = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC); |
103 | 114 | secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC); |
104 | 115 | |
105 | while (secs != secs2 && timeout--) { | |
116 | while (secs != secs2 && --timeout) { | |
106 | 117 | secs = secs2; |
107 | 118 | secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC); |
108 | 119 | } |
... | ... | |
119 | 130 | { |
120 | 131 | struct jz4740_rtc *rtc = dev_get_drvdata(dev); |
121 | 132 | |
122 | if ((uint32_t)secs != secs) | |
123 | return -EINVAL; | |
124 | ||
125 | jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, secs); | |
126 | ||
127 | return 0; | |
133 | return jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, secs); | |
128 | 134 | } |
129 | 135 | |
130 | 136 | static int jz4740_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
... | ... | |
147 | 153 | |
148 | 154 | static int jz4740_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
149 | 155 | { |
156 | int ret; | |
150 | 157 | struct jz4740_rtc *rtc = dev_get_drvdata(dev); |
151 | 158 | unsigned long secs; |
152 | 159 | |
153 | 160 | rtc_tm_to_time(&alrm->time, &secs); |
154 | 161 | |
155 | if ((uint32_t)secs != secs) | |
156 | return -EINVAL; | |
157 | ||
158 | jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC_ALARM, (uint32_t)secs); | |
159 | jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_AE, | |
160 | alrm->enabled ? JZ_RTC_CTRL_AE : 0); | |
162 | ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC_ALARM, secs); | |
163 | if (!ret) | |
164 | ret = jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_AE, alrm->enabled); | |
161 | 165 | |
162 | return 0; | |
163 | } | |
164 | ||
165 | static inline int jz4740_irq_enable(struct device *dev, int irq, unsigned int enable) | |
166 | { | |
167 | struct jz4740_rtc *rtc = dev_get_drvdata(dev); | |
168 | jz4740_rtc_ctrl_set_bits(rtc, irq, enable ? irq : 0); | |
169 | ||
170 | return 0; | |
166 | return ret; | |
171 | 167 | } |
172 | 168 | |
173 | 169 | static int jz4740_rtc_update_irq_enable(struct device *dev, unsigned int enable) |
174 | 170 | { |
175 | return jz4740_irq_enable(dev, JZ_RTC_CTRL_1HZ_IRQ, enable); | |
171 | struct jz4740_rtc *rtc = dev_get_drvdata(dev); | |
172 | return jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_1HZ_IRQ, enable); | |
176 | 173 | } |
177 | 174 | |
178 | 175 | static int jz4740_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) |
179 | 176 | { |
180 | return jz4740_irq_enable(dev, JZ_RTC_CTRL_AF_IRQ, enable); | |
177 | struct jz4740_rtc *rtc = dev_get_drvdata(dev); | |
178 | return jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_AF_IRQ, enable); | |
181 | 179 | } |
182 | 180 | |
183 | 181 | static struct rtc_class_ops jz4740_rtc_ops = { |
... | ... | |
194 | 192 | struct jz4740_rtc *rtc = data; |
195 | 193 | uint32_t ctrl; |
196 | 194 | unsigned long events = 0; |
195 | ||
197 | 196 | ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL); |
198 | 197 | |
199 | 198 | if (ctrl & JZ_RTC_CTRL_1HZ) |
... | ... | |
204 | 203 | |
205 | 204 | rtc_update_irq(rtc->rtc, 1, events); |
206 | 205 | |
207 | jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_1HZ | JZ_RTC_CTRL_AF, 0); | |
206 | jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_1HZ | JZ_RTC_CTRL_AF, false); | |
208 | 207 | |
209 | 208 | return IRQ_HANDLED; |
210 | 209 | } |
... | ... | |
276 | 275 | |
277 | 276 | scratchpad = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SCRATCHPAD); |
278 | 277 | if (scratchpad != 0x12345678) { |
279 | jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SCRATCHPAD, 0x12345678); | |
280 | jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, 0); | |
278 | ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SCRATCHPAD, 0x12345678); | |
279 | ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, 0); | |
280 | if (ret) { | |
281 | dev_err(&pdev->dev, "Could not write write to RTC registers\n"); | |
282 | goto err_free_irq; | |
283 | } | |
281 | 284 | } |
282 | 285 | |
283 | 286 | return 0; |
284 | 287 | |
288 | err_free_irq: | |
289 | free_irq(rtc->irq, rtc); | |
285 | 290 | err_unregister_rtc: |
286 | 291 | rtc_device_unregister(rtc->rtc); |
287 | 292 | err_iounmap: |
... | ... | |
336 | 341 | |
337 | 342 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); |
338 | 343 | MODULE_LICENSE("GPL"); |
339 | MODULE_DESCRIPTION("RTC driver for the JZ4720/JZ4740 SoC\n"); | |
344 | MODULE_DESCRIPTION("RTC driver for the JZ4740 SoC\n"); | |
340 | 345 | MODULE_ALIAS("platform:jz4740-rtc"); |
Branches:
ben-wpan
ben-wpan-stefan
5396a9238205f20f811ea57898980d3ca82df0b6
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