Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
rtc-mpc5121.c
Go to the documentation of this file.
1 /*
2  * Real-time clock driver for MPC5121
3  *
4  * Copyright 2007, Domen Puncer <[email protected]>
5  * Copyright 2008, Freescale Semiconductor, Inc. All rights reserved.
6  * Copyright 2011, Dmitry Eremin-Solenikov
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  */
12 
13 #include <linux/init.h>
14 #include <linux/module.h>
15 #include <linux/rtc.h>
16 #include <linux/of_device.h>
17 #include <linux/of_platform.h>
18 #include <linux/io.h>
19 #include <linux/slab.h>
20 
22  u8 set_time; /* RTC + 0x00 */
23  u8 hour_set; /* RTC + 0x01 */
24  u8 minute_set; /* RTC + 0x02 */
25  u8 second_set; /* RTC + 0x03 */
26 
27  u8 set_date; /* RTC + 0x04 */
28  u8 month_set; /* RTC + 0x05 */
29  u8 weekday_set; /* RTC + 0x06 */
30  u8 date_set; /* RTC + 0x07 */
31 
32  u8 write_sw; /* RTC + 0x08 */
33  u8 sw_set; /* RTC + 0x09 */
34  u16 year_set; /* RTC + 0x0a */
35 
36  u8 alm_enable; /* RTC + 0x0c */
37  u8 alm_hour_set; /* RTC + 0x0d */
38  u8 alm_min_set; /* RTC + 0x0e */
39  u8 int_enable; /* RTC + 0x0f */
40 
42  u8 hour; /* RTC + 0x11 */
43  u8 minute; /* RTC + 0x12 */
44  u8 second; /* RTC + 0x13 */
45 
46  u8 month; /* RTC + 0x14 */
47  u8 wday_mday; /* RTC + 0x15 */
48  u16 year; /* RTC + 0x16 */
49 
50  u8 int_alm; /* RTC + 0x18 */
51  u8 int_sw; /* RTC + 0x19 */
52  u8 alm_status; /* RTC + 0x1a */
53  u8 sw_minute; /* RTC + 0x1b */
54 
55  u8 bus_error_1; /* RTC + 0x1c */
56  u8 int_day; /* RTC + 0x1d */
57  u8 int_min; /* RTC + 0x1e */
58  u8 int_sec; /* RTC + 0x1f */
59 
60  /*
61  * target_time:
62  * intended to be used for hibernation but hibernation
63  * does not work on silicon rev 1.5 so use it for non-volatile
64  * storage of offset between the actual_time register and linux
65  * time
66  */
67  u32 target_time; /* RTC + 0x20 */
68  /*
69  * actual_time:
70  * readonly time since VBAT_RTC was last connected
71  */
72  u32 actual_time; /* RTC + 0x24 */
73  u32 keep_alive; /* RTC + 0x28 */
74 };
75 
77  unsigned irq;
78  unsigned irq_periodic;
80  struct rtc_device *rtc;
82 };
83 
84 /*
85  * Update second/minute/hour registers.
86  *
87  * This is just so alarm will work.
88  */
89 static void mpc5121_rtc_update_smh(struct mpc5121_rtc_regs __iomem *regs,
90  struct rtc_time *tm)
91 {
92  out_8(&regs->second_set, tm->tm_sec);
93  out_8(&regs->minute_set, tm->tm_min);
94  out_8(&regs->hour_set, tm->tm_hour);
95 
96  /* set time sequence */
97  out_8(&regs->set_time, 0x1);
98  out_8(&regs->set_time, 0x3);
99  out_8(&regs->set_time, 0x1);
100  out_8(&regs->set_time, 0x0);
101 }
102 
103 static int mpc5121_rtc_read_time(struct device *dev, struct rtc_time *tm)
104 {
105  struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev);
106  struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
107  unsigned long now;
108 
109  /*
110  * linux time is actual_time plus the offset saved in target_time
111  */
112  now = in_be32(&regs->actual_time) + in_be32(&regs->target_time);
113 
114  rtc_time_to_tm(now, tm);
115 
116  /*
117  * update second minute hour registers
118  * so alarms will work
119  */
120  mpc5121_rtc_update_smh(regs, tm);
121 
122  return rtc_valid_tm(tm);
123 }
124 
125 static int mpc5121_rtc_set_time(struct device *dev, struct rtc_time *tm)
126 {
127  struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev);
128  struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
129  int ret;
130  unsigned long now;
131 
132  /*
133  * The actual_time register is read only so we write the offset
134  * between it and linux time to the target_time register.
135  */
136  ret = rtc_tm_to_time(tm, &now);
137  if (ret == 0)
138  out_be32(&regs->target_time, now - in_be32(&regs->actual_time));
139 
140  /*
141  * update second minute hour registers
142  * so alarms will work
143  */
144  mpc5121_rtc_update_smh(regs, tm);
145 
146  return 0;
147 }
148 
149 static int mpc5200_rtc_read_time(struct device *dev, struct rtc_time *tm)
150 {
151  struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev);
152  struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
153  int tmp;
154 
155  tm->tm_sec = in_8(&regs->second);
156  tm->tm_min = in_8(&regs->minute);
157 
158  /* 12 hour format? */
159  if (in_8(&regs->hour) & 0x20)
160  tm->tm_hour = (in_8(&regs->hour) >> 1) +
161  (in_8(&regs->hour) & 1 ? 12 : 0);
162  else
163  tm->tm_hour = in_8(&regs->hour);
164 
165  tmp = in_8(&regs->wday_mday);
166  tm->tm_mday = tmp & 0x1f;
167  tm->tm_mon = in_8(&regs->month) - 1;
168  tm->tm_year = in_be16(&regs->year) - 1900;
169  tm->tm_wday = (tmp >> 5) % 7;
170  tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year);
171  tm->tm_isdst = 0;
172 
173  return 0;
174 }
175 
176 static int mpc5200_rtc_set_time(struct device *dev, struct rtc_time *tm)
177 {
178  struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev);
179  struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
180 
181  mpc5121_rtc_update_smh(regs, tm);
182 
183  /* date */
184  out_8(&regs->month_set, tm->tm_mon + 1);
185  out_8(&regs->weekday_set, tm->tm_wday ? tm->tm_wday : 7);
186  out_8(&regs->date_set, tm->tm_mday);
187  out_be16(&regs->year_set, tm->tm_year + 1900);
188 
189  /* set date sequence */
190  out_8(&regs->set_date, 0x1);
191  out_8(&regs->set_date, 0x3);
192  out_8(&regs->set_date, 0x1);
193  out_8(&regs->set_date, 0x0);
194 
195  return 0;
196 }
197 
198 static int mpc5121_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
199 {
200  struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev);
201  struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
202 
203  *alarm = rtc->wkalarm;
204 
205  alarm->pending = in_8(&regs->alm_status);
206 
207  return 0;
208 }
209 
210 static int mpc5121_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
211 {
212  struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev);
213  struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
214 
215  /*
216  * the alarm has no seconds so deal with it
217  */
218  if (alarm->time.tm_sec) {
219  alarm->time.tm_sec = 0;
220  alarm->time.tm_min++;
221  if (alarm->time.tm_min >= 60) {
222  alarm->time.tm_min = 0;
223  alarm->time.tm_hour++;
224  if (alarm->time.tm_hour >= 24)
225  alarm->time.tm_hour = 0;
226  }
227  }
228 
229  alarm->time.tm_mday = -1;
230  alarm->time.tm_mon = -1;
231  alarm->time.tm_year = -1;
232 
233  out_8(&regs->alm_min_set, alarm->time.tm_min);
234  out_8(&regs->alm_hour_set, alarm->time.tm_hour);
235 
236  out_8(&regs->alm_enable, alarm->enabled);
237 
238  rtc->wkalarm = *alarm;
239  return 0;
240 }
241 
242 static irqreturn_t mpc5121_rtc_handler(int irq, void *dev)
243 {
244  struct mpc5121_rtc_data *rtc = dev_get_drvdata((struct device *)dev);
245  struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
246 
247  if (in_8(&regs->int_alm)) {
248  /* acknowledge and clear status */
249  out_8(&regs->int_alm, 1);
250  out_8(&regs->alm_status, 1);
251 
252  rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF);
253  return IRQ_HANDLED;
254  }
255 
256  return IRQ_NONE;
257 }
258 
259 static irqreturn_t mpc5121_rtc_handler_upd(int irq, void *dev)
260 {
261  struct mpc5121_rtc_data *rtc = dev_get_drvdata((struct device *)dev);
262  struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
263 
264  if (in_8(&regs->int_sec) && (in_8(&regs->int_enable) & 0x1)) {
265  /* acknowledge */
266  out_8(&regs->int_sec, 1);
267 
268  rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_UF);
269  return IRQ_HANDLED;
270  }
271 
272  return IRQ_NONE;
273 }
274 
275 static int mpc5121_rtc_alarm_irq_enable(struct device *dev,
276  unsigned int enabled)
277 {
278  struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev);
279  struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
280  int val;
281 
282  if (enabled)
283  val = 1;
284  else
285  val = 0;
286 
287  out_8(&regs->alm_enable, val);
288  rtc->wkalarm.enabled = val;
289 
290  return 0;
291 }
292 
293 static const struct rtc_class_ops mpc5121_rtc_ops = {
294  .read_time = mpc5121_rtc_read_time,
295  .set_time = mpc5121_rtc_set_time,
296  .read_alarm = mpc5121_rtc_read_alarm,
297  .set_alarm = mpc5121_rtc_set_alarm,
298  .alarm_irq_enable = mpc5121_rtc_alarm_irq_enable,
299 };
300 
301 static const struct rtc_class_ops mpc5200_rtc_ops = {
302  .read_time = mpc5200_rtc_read_time,
303  .set_time = mpc5200_rtc_set_time,
304  .read_alarm = mpc5121_rtc_read_alarm,
305  .set_alarm = mpc5121_rtc_set_alarm,
306  .alarm_irq_enable = mpc5121_rtc_alarm_irq_enable,
307 };
308 
309 static int __devinit mpc5121_rtc_probe(struct platform_device *op)
310 {
311  struct mpc5121_rtc_data *rtc;
312  int err = 0;
313 
314  rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);
315  if (!rtc)
316  return -ENOMEM;
317 
318  rtc->regs = of_iomap(op->dev.of_node, 0);
319  if (!rtc->regs) {
320  dev_err(&op->dev, "%s: couldn't map io space\n", __func__);
321  err = -ENOSYS;
322  goto out_free;
323  }
324 
325  device_init_wakeup(&op->dev, 1);
326 
327  dev_set_drvdata(&op->dev, rtc);
328 
329  rtc->irq = irq_of_parse_and_map(op->dev.of_node, 1);
330  err = request_irq(rtc->irq, mpc5121_rtc_handler, 0,
331  "mpc5121-rtc", &op->dev);
332  if (err) {
333  dev_err(&op->dev, "%s: could not request irq: %i\n",
334  __func__, rtc->irq);
335  goto out_dispose;
336  }
337 
338  rtc->irq_periodic = irq_of_parse_and_map(op->dev.of_node, 0);
339  err = request_irq(rtc->irq_periodic, mpc5121_rtc_handler_upd,
340  0, "mpc5121-rtc_upd", &op->dev);
341  if (err) {
342  dev_err(&op->dev, "%s: could not request irq: %i\n",
343  __func__, rtc->irq_periodic);
344  goto out_dispose2;
345  }
346 
347  if (of_device_is_compatible(op->dev.of_node, "fsl,mpc5121-rtc")) {
348  u32 ka;
349  ka = in_be32(&rtc->regs->keep_alive);
350  if (ka & 0x02) {
351  dev_warn(&op->dev,
352  "mpc5121-rtc: Battery or oscillator failure!\n");
353  out_be32(&rtc->regs->keep_alive, ka);
354  }
355 
356  rtc->rtc = rtc_device_register("mpc5121-rtc", &op->dev,
357  &mpc5121_rtc_ops, THIS_MODULE);
358  } else {
359  rtc->rtc = rtc_device_register("mpc5200-rtc", &op->dev,
360  &mpc5200_rtc_ops, THIS_MODULE);
361  }
362 
363  if (IS_ERR(rtc->rtc)) {
364  err = PTR_ERR(rtc->rtc);
365  goto out_free_irq;
366  }
367  rtc->rtc->uie_unsupported = 1;
368 
369  return 0;
370 
371 out_free_irq:
372  free_irq(rtc->irq_periodic, &op->dev);
373 out_dispose2:
375  free_irq(rtc->irq, &op->dev);
376 out_dispose:
377  irq_dispose_mapping(rtc->irq);
378  iounmap(rtc->regs);
379 out_free:
380  kfree(rtc);
381 
382  return err;
383 }
384 
385 static int __devexit mpc5121_rtc_remove(struct platform_device *op)
386 {
387  struct mpc5121_rtc_data *rtc = dev_get_drvdata(&op->dev);
388  struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
389 
390  /* disable interrupt, so there are no nasty surprises */
391  out_8(&regs->alm_enable, 0);
392  out_8(&regs->int_enable, in_8(&regs->int_enable) & ~0x1);
393 
395  iounmap(rtc->regs);
396  free_irq(rtc->irq, &op->dev);
397  free_irq(rtc->irq_periodic, &op->dev);
398  irq_dispose_mapping(rtc->irq);
400  dev_set_drvdata(&op->dev, NULL);
401  kfree(rtc);
402 
403  return 0;
404 }
405 
406 static struct of_device_id mpc5121_rtc_match[] __devinitdata = {
407  { .compatible = "fsl,mpc5121-rtc", },
408  { .compatible = "fsl,mpc5200-rtc", },
409  {},
410 };
411 
412 static struct platform_driver mpc5121_rtc_driver = {
413  .driver = {
414  .name = "mpc5121-rtc",
415  .owner = THIS_MODULE,
416  .of_match_table = mpc5121_rtc_match,
417  },
418  .probe = mpc5121_rtc_probe,
419  .remove = __devexit_p(mpc5121_rtc_remove),
420 };
421 
422 module_platform_driver(mpc5121_rtc_driver);
423 
424 MODULE_LICENSE("GPL");
425 MODULE_AUTHOR("John Rigby <[email protected]>");