aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc/rtc-sa1100.c
diff options
context:
space:
mode:
authorMarcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br>2011-02-07 16:16:08 -0500
committerJohn Stultz <john.stultz@linaro.org>2011-03-09 14:25:08 -0500
commit416f0e8056f757c119dc3d4fa434a62b65c8272b (patch)
tree30ec5a34ddcf781d950c0d907e1f52acc42a2350 /drivers/rtc/rtc-sa1100.c
parenta417493ef916b8b6d1782a589766a713c553842e (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.c111
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
45static const unsigned long RTC_FREQ = 1024; 45static const unsigned long RTC_FREQ = 1024;
46static unsigned long timer_freq;
47static struct rtc_time rtc_alarm; 46static struct rtc_time rtc_alarm;
48static DEFINE_SPINLOCK(sa1100_rtc_lock); 47static 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
159static 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
172static int rtc_timer1_count;
173
174static 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
194static 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
220static 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
246static int sa1100_rtc_open(struct device *dev) 158static 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
296static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) 199static 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
360static const struct rtc_class_ops sa1100_rtc_ops = { 263static 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 *