diff options
author | Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br> | 2011-02-07 16:16:08 -0500 |
---|---|---|
committer | John Stultz <john.stultz@linaro.org> | 2011-03-09 14:25:08 -0500 |
commit | 416f0e8056f757c119dc3d4fa434a62b65c8272b (patch) | |
tree | 30ec5a34ddcf781d950c0d907e1f52acc42a2350 /drivers/rtc/rtc-sa1100.c | |
parent | a417493ef916b8b6d1782a589766a713c553842e (diff) |
RTC: sa1100: Update the sa1100 RTC driver.
Since PIE interrupts are now emulated, this patch removes the previous
code that used the hardware counters.
The removal of read_callback() also fixes a wrong user space behaviour
of this driver, which was not returning the right value to read().
[john.stultz: Merge fixups]
CC: Thomas Gleixner <tglx@linutronix.de>
CC: Alessandro Zummo <a.zummo@towertech.it>
CC: Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br>
CC: rtc-linux@googlegroups.com
Signed-off-by: Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Diffstat (limited to 'drivers/rtc/rtc-sa1100.c')
-rw-r--r-- | drivers/rtc/rtc-sa1100.c | 111 |
1 files changed, 3 insertions, 108 deletions
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index 41f62ca68dc4..0b40bb88a884 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c | |||
@@ -43,7 +43,6 @@ | |||
43 | #define RTC_DEF_TRIM 0 | 43 | #define RTC_DEF_TRIM 0 |
44 | 44 | ||
45 | static const unsigned long RTC_FREQ = 1024; | 45 | static const unsigned long RTC_FREQ = 1024; |
46 | static unsigned long timer_freq; | ||
47 | static struct rtc_time rtc_alarm; | 46 | static struct rtc_time rtc_alarm; |
48 | static DEFINE_SPINLOCK(sa1100_rtc_lock); | 47 | static DEFINE_SPINLOCK(sa1100_rtc_lock); |
49 | 48 | ||
@@ -156,97 +155,11 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) | |||
156 | return IRQ_HANDLED; | 155 | return IRQ_HANDLED; |
157 | } | 156 | } |
158 | 157 | ||
159 | static int sa1100_irq_set_freq(struct device *dev, int freq) | ||
160 | { | ||
161 | if (freq < 1 || freq > timer_freq) { | ||
162 | return -EINVAL; | ||
163 | } else { | ||
164 | struct rtc_device *rtc = (struct rtc_device *)dev; | ||
165 | |||
166 | rtc->irq_freq = freq; | ||
167 | |||
168 | return 0; | ||
169 | } | ||
170 | } | ||
171 | |||
172 | static int rtc_timer1_count; | ||
173 | |||
174 | static inline int sa1100_timer1_retrigger(struct rtc_device *rtc) | ||
175 | { | ||
176 | unsigned long diff; | ||
177 | unsigned long period = timer_freq / rtc->irq_freq; | ||
178 | |||
179 | spin_lock_irq(&sa1100_rtc_lock); | ||
180 | |||
181 | do { | ||
182 | OSMR1 += period; | ||
183 | diff = OSMR1 - OSCR; | ||
184 | /* If OSCR > OSMR1, diff is a very large number (unsigned | ||
185 | * math). This means we have a lost interrupt. */ | ||
186 | } while (diff > period); | ||
187 | OIER |= OIER_E1; | ||
188 | |||
189 | spin_unlock_irq(&sa1100_rtc_lock); | ||
190 | |||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | static irqreturn_t timer1_interrupt(int irq, void *dev_id) | ||
195 | { | ||
196 | struct platform_device *pdev = to_platform_device(dev_id); | ||
197 | struct rtc_device *rtc = platform_get_drvdata(pdev); | ||
198 | |||
199 | /* | ||
200 | * If we match for the first time, rtc_timer1_count will be 1. | ||
201 | * Otherwise, we wrapped around (very unlikely but | ||
202 | * still possible) so compute the amount of missed periods. | ||
203 | * The match reg is updated only when the data is actually retrieved | ||
204 | * to avoid unnecessary interrupts. | ||
205 | */ | ||
206 | OSSR = OSSR_M1; /* clear match on timer1 */ | ||
207 | |||
208 | rtc_update_irq(rtc, rtc_timer1_count, RTC_PF | RTC_IRQF); | ||
209 | |||
210 | if (rtc_timer1_count == 1) | ||
211 | rtc_timer1_count = | ||
212 | (rtc->irq_freq * ((1 << 30) / (timer_freq >> 2))); | ||
213 | |||
214 | /* retrigger. */ | ||
215 | sa1100_timer1_retrigger(rtc); | ||
216 | |||
217 | return IRQ_HANDLED; | ||
218 | } | ||
219 | |||
220 | static int sa1100_rtc_read_callback(struct device *dev, int data) | ||
221 | { | ||
222 | if (data & RTC_PF) { | ||
223 | struct rtc_device *rtc = (struct rtc_device *)dev; | ||
224 | |||
225 | /* interpolate missed periods and set match for the next */ | ||
226 | unsigned long period = timer_freq / rtc->irq_freq; | ||
227 | unsigned long oscr = OSCR; | ||
228 | unsigned long osmr1 = OSMR1; | ||
229 | unsigned long missed = (oscr - osmr1)/period; | ||
230 | data += missed << 8; | ||
231 | OSSR = OSSR_M1; /* clear match on timer 1 */ | ||
232 | OSMR1 = osmr1 + (missed + 1)*period; | ||
233 | /* Ensure we didn't miss another match in the mean time. | ||
234 | * Here we compare (match - OSCR) 8 instead of 0 -- | ||
235 | * see comment in pxa_timer_interrupt() for explanation. | ||
236 | */ | ||
237 | while ((signed long)((osmr1 = OSMR1) - OSCR) <= 8) { | ||
238 | data += 0x100; | ||
239 | OSSR = OSSR_M1; /* clear match on timer 1 */ | ||
240 | OSMR1 = osmr1 + period; | ||
241 | } | ||
242 | } | ||
243 | return data; | ||
244 | } | ||
245 | |||
246 | static int sa1100_rtc_open(struct device *dev) | 158 | static int sa1100_rtc_open(struct device *dev) |
247 | { | 159 | { |
248 | int ret; | 160 | int ret; |
249 | struct rtc_device *rtc = (struct rtc_device *)dev; | 161 | struct platform_device *plat_dev = to_platform_device(dev); |
162 | struct rtc_device *rtc = platform_get_drvdata(plat_dev); | ||
250 | 163 | ||
251 | ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, IRQF_DISABLED, | 164 | ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, IRQF_DISABLED, |
252 | "rtc 1Hz", dev); | 165 | "rtc 1Hz", dev); |
@@ -260,19 +173,11 @@ static int sa1100_rtc_open(struct device *dev) | |||
260 | dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm); | 173 | dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm); |
261 | goto fail_ai; | 174 | goto fail_ai; |
262 | } | 175 | } |
263 | ret = request_irq(IRQ_OST1, timer1_interrupt, IRQF_DISABLED, | ||
264 | "rtc timer", dev); | ||
265 | if (ret) { | ||
266 | dev_err(dev, "IRQ %d already in use.\n", IRQ_OST1); | ||
267 | goto fail_pi; | ||
268 | } | ||
269 | rtc->max_user_freq = RTC_FREQ; | 176 | rtc->max_user_freq = RTC_FREQ; |
270 | sa1100_irq_set_freq(dev, RTC_FREQ); | 177 | rtc_irq_set_freq(rtc, NULL, RTC_FREQ); |
271 | 178 | ||
272 | return 0; | 179 | return 0; |
273 | 180 | ||
274 | fail_pi: | ||
275 | free_irq(IRQ_RTCAlrm, dev); | ||
276 | fail_ai: | 181 | fail_ai: |
277 | free_irq(IRQ_RTC1Hz, dev); | 182 | free_irq(IRQ_RTC1Hz, dev); |
278 | fail_ui: | 183 | fail_ui: |
@@ -287,12 +192,10 @@ static void sa1100_rtc_release(struct device *dev) | |||
287 | OSSR = OSSR_M1; | 192 | OSSR = OSSR_M1; |
288 | spin_unlock_irq(&sa1100_rtc_lock); | 193 | spin_unlock_irq(&sa1100_rtc_lock); |
289 | 194 | ||
290 | free_irq(IRQ_OST1, dev); | ||
291 | free_irq(IRQ_RTCAlrm, dev); | 195 | free_irq(IRQ_RTCAlrm, dev); |
292 | free_irq(IRQ_RTC1Hz, dev); | 196 | free_irq(IRQ_RTC1Hz, dev); |
293 | } | 197 | } |
294 | 198 | ||
295 | |||
296 | static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | 199 | static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) |
297 | { | 200 | { |
298 | spin_lock_irq(&sa1100_rtc_lock); | 201 | spin_lock_irq(&sa1100_rtc_lock); |
@@ -359,7 +262,6 @@ static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq) | |||
359 | 262 | ||
360 | static const struct rtc_class_ops sa1100_rtc_ops = { | 263 | static const struct rtc_class_ops sa1100_rtc_ops = { |
361 | .open = sa1100_rtc_open, | 264 | .open = sa1100_rtc_open, |
362 | .read_callback = sa1100_rtc_read_callback, | ||
363 | .release = sa1100_rtc_release, | 265 | .release = sa1100_rtc_release, |
364 | .read_time = sa1100_rtc_read_time, | 266 | .read_time = sa1100_rtc_read_time, |
365 | .set_time = sa1100_rtc_set_time, | 267 | .set_time = sa1100_rtc_set_time, |
@@ -373,8 +275,6 @@ static int sa1100_rtc_probe(struct platform_device *pdev) | |||
373 | { | 275 | { |
374 | struct rtc_device *rtc; | 276 | struct rtc_device *rtc; |
375 | 277 | ||
376 | timer_freq = get_clock_tick_rate(); | ||
377 | |||
378 | /* | 278 | /* |
379 | * According to the manual we should be able to let RTTR be zero | 279 | * According to the manual we should be able to let RTTR be zero |
380 | * and then a default diviser for a 32.768KHz clock is used. | 280 | * and then a default diviser for a 32.768KHz clock is used. |
@@ -400,11 +300,6 @@ static int sa1100_rtc_probe(struct platform_device *pdev) | |||
400 | 300 | ||
401 | platform_set_drvdata(pdev, rtc); | 301 | platform_set_drvdata(pdev, rtc); |
402 | 302 | ||
403 | /* Set the irq_freq */ | ||
404 | /*TODO: Find out who is messing with this value after we initialize | ||
405 | * it here.*/ | ||
406 | rtc->irq_freq = RTC_FREQ; | ||
407 | |||
408 | /* Fix for a nasty initialization problem the in SA11xx RTSR register. | 303 | /* Fix for a nasty initialization problem the in SA11xx RTSR register. |
409 | * See also the comments in sa1100_rtc_interrupt(). | 304 | * See also the comments in sa1100_rtc_interrupt(). |
410 | * | 305 | * |