Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
rtc-pcf50633.c
Go to the documentation of this file.
1 /* NXP PCF50633 RTC Driver
2  *
3  * (C) 2006-2008 by Openmoko, Inc.
4  * Author: Balaji Rao <[email protected]>
5  * All rights reserved.
6  *
7  * Broken down from monstrous PCF50633 driver mainly by
8  * Harald Welte, Andy Green and Werner Almesberger
9  *
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU General Public License as published by the
12  * Free Software Foundation; either version 2 of the License, or (at your
13  * option) any later version.
14  *
15  */
16 
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/init.h>
20 #include <linux/device.h>
21 #include <linux/slab.h>
22 #include <linux/platform_device.h>
23 #include <linux/rtc.h>
24 #include <linux/bcd.h>
25 #include <linux/err.h>
26 
28 
29 #define PCF50633_REG_RTCSC 0x59 /* Second */
30 #define PCF50633_REG_RTCMN 0x5a /* Minute */
31 #define PCF50633_REG_RTCHR 0x5b /* Hour */
32 #define PCF50633_REG_RTCWD 0x5c /* Weekday */
33 #define PCF50633_REG_RTCDT 0x5d /* Day */
34 #define PCF50633_REG_RTCMT 0x5e /* Month */
35 #define PCF50633_REG_RTCYR 0x5f /* Year */
36 #define PCF50633_REG_RTCSCA 0x60 /* Alarm Second */
37 #define PCF50633_REG_RTCMNA 0x61 /* Alarm Minute */
38 #define PCF50633_REG_RTCHRA 0x62 /* Alarm Hour */
39 #define PCF50633_REG_RTCWDA 0x63 /* Alarm Weekday */
40 #define PCF50633_REG_RTCDTA 0x64 /* Alarm Day */
41 #define PCF50633_REG_RTCMTA 0x65 /* Alarm Month */
42 #define PCF50633_REG_RTCYRA 0x66 /* Alarm Year */
43 
52  PCF50633_TI_EXTENT /* always last */
53 };
54 
55 struct pcf50633_time {
57 };
58 
59 struct pcf50633_rtc {
62 
63  struct pcf50633 *pcf;
65 };
66 
67 static void pcf2rtc_time(struct rtc_time *rtc, struct pcf50633_time *pcf)
68 {
69  rtc->tm_sec = bcd2bin(pcf->time[PCF50633_TI_SEC]);
70  rtc->tm_min = bcd2bin(pcf->time[PCF50633_TI_MIN]);
71  rtc->tm_hour = bcd2bin(pcf->time[PCF50633_TI_HOUR]);
72  rtc->tm_wday = bcd2bin(pcf->time[PCF50633_TI_WKDAY]);
73  rtc->tm_mday = bcd2bin(pcf->time[PCF50633_TI_DAY]);
74  rtc->tm_mon = bcd2bin(pcf->time[PCF50633_TI_MONTH]) - 1;
75  rtc->tm_year = bcd2bin(pcf->time[PCF50633_TI_YEAR]) + 100;
76 }
77 
78 static void rtc2pcf_time(struct pcf50633_time *pcf, struct rtc_time *rtc)
79 {
80  pcf->time[PCF50633_TI_SEC] = bin2bcd(rtc->tm_sec);
81  pcf->time[PCF50633_TI_MIN] = bin2bcd(rtc->tm_min);
82  pcf->time[PCF50633_TI_HOUR] = bin2bcd(rtc->tm_hour);
83  pcf->time[PCF50633_TI_WKDAY] = bin2bcd(rtc->tm_wday);
84  pcf->time[PCF50633_TI_DAY] = bin2bcd(rtc->tm_mday);
85  pcf->time[PCF50633_TI_MONTH] = bin2bcd(rtc->tm_mon + 1);
86  pcf->time[PCF50633_TI_YEAR] = bin2bcd(rtc->tm_year % 100);
87 }
88 
89 static int
90 pcf50633_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
91 {
92  struct pcf50633_rtc *rtc = dev_get_drvdata(dev);
93  int err;
94 
95  if (enabled)
97  else
99 
100  if (err < 0)
101  return err;
102 
103  rtc->alarm_enabled = enabled;
104 
105  return 0;
106 }
107 
108 static int pcf50633_rtc_read_time(struct device *dev, struct rtc_time *tm)
109 {
110  struct pcf50633_rtc *rtc;
111  struct pcf50633_time pcf_tm;
112  int ret;
113 
114  rtc = dev_get_drvdata(dev);
115 
118  &pcf_tm.time[0]);
119  if (ret != PCF50633_TI_EXTENT) {
120  dev_err(dev, "Failed to read time\n");
121  return -EIO;
122  }
123 
124  dev_dbg(dev, "PCF_TIME: %02x.%02x.%02x %02x:%02x:%02x\n",
125  pcf_tm.time[PCF50633_TI_DAY],
126  pcf_tm.time[PCF50633_TI_MONTH],
127  pcf_tm.time[PCF50633_TI_YEAR],
128  pcf_tm.time[PCF50633_TI_HOUR],
129  pcf_tm.time[PCF50633_TI_MIN],
130  pcf_tm.time[PCF50633_TI_SEC]);
131 
132  pcf2rtc_time(tm, &pcf_tm);
133 
134  dev_dbg(dev, "RTC_TIME: %u.%u.%u %u:%u:%u\n",
135  tm->tm_mday, tm->tm_mon, tm->tm_year,
136  tm->tm_hour, tm->tm_min, tm->tm_sec);
137 
138  return rtc_valid_tm(tm);
139 }
140 
141 static int pcf50633_rtc_set_time(struct device *dev, struct rtc_time *tm)
142 {
143  struct pcf50633_rtc *rtc;
144  struct pcf50633_time pcf_tm;
145  int alarm_masked, ret = 0;
146 
147  rtc = dev_get_drvdata(dev);
148 
149  dev_dbg(dev, "RTC_TIME: %u.%u.%u %u:%u:%u\n",
150  tm->tm_mday, tm->tm_mon, tm->tm_year,
151  tm->tm_hour, tm->tm_min, tm->tm_sec);
152 
153  rtc2pcf_time(&pcf_tm, tm);
154 
155  dev_dbg(dev, "PCF_TIME: %02x.%02x.%02x %02x:%02x:%02x\n",
156  pcf_tm.time[PCF50633_TI_DAY],
157  pcf_tm.time[PCF50633_TI_MONTH],
158  pcf_tm.time[PCF50633_TI_YEAR],
159  pcf_tm.time[PCF50633_TI_HOUR],
160  pcf_tm.time[PCF50633_TI_MIN],
161  pcf_tm.time[PCF50633_TI_SEC]);
162 
163 
164  alarm_masked = pcf50633_irq_mask_get(rtc->pcf, PCF50633_IRQ_ALARM);
165 
166  if (!alarm_masked)
168 
169  /* Returns 0 on success */
172  &pcf_tm.time[0]);
173 
174  if (!alarm_masked)
176 
177  return ret;
178 }
179 
180 static int pcf50633_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
181 {
182  struct pcf50633_rtc *rtc;
183  struct pcf50633_time pcf_tm;
184  int ret = 0;
185 
186  rtc = dev_get_drvdata(dev);
187 
188  alrm->enabled = rtc->alarm_enabled;
189  alrm->pending = rtc->alarm_pending;
190 
192  PCF50633_TI_EXTENT, &pcf_tm.time[0]);
193  if (ret != PCF50633_TI_EXTENT) {
194  dev_err(dev, "Failed to read time\n");
195  return -EIO;
196  }
197 
198  pcf2rtc_time(&alrm->time, &pcf_tm);
199 
200  return rtc_valid_tm(&alrm->time);
201 }
202 
203 static int pcf50633_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
204 {
205  struct pcf50633_rtc *rtc;
206  struct pcf50633_time pcf_tm;
207  int alarm_masked, ret = 0;
208 
209  rtc = dev_get_drvdata(dev);
210 
211  rtc2pcf_time(&pcf_tm, &alrm->time);
212 
213  /* do like mktime does and ignore tm_wday */
214  pcf_tm.time[PCF50633_TI_WKDAY] = 7;
215 
216  alarm_masked = pcf50633_irq_mask_get(rtc->pcf, PCF50633_IRQ_ALARM);
217 
218  /* disable alarm interrupt */
219  if (!alarm_masked)
221 
222  /* Returns 0 on success */
224  PCF50633_TI_EXTENT, &pcf_tm.time[0]);
225  if (!alrm->enabled)
226  rtc->alarm_pending = 0;
227 
228  if (!alarm_masked || alrm->enabled)
230  rtc->alarm_enabled = alrm->enabled;
231 
232  return ret;
233 }
234 
235 static struct rtc_class_ops pcf50633_rtc_ops = {
236  .read_time = pcf50633_rtc_read_time,
237  .set_time = pcf50633_rtc_set_time,
238  .read_alarm = pcf50633_rtc_read_alarm,
239  .set_alarm = pcf50633_rtc_set_alarm,
240  .alarm_irq_enable = pcf50633_rtc_alarm_irq_enable,
241 };
242 
243 static void pcf50633_rtc_irq(int irq, void *data)
244 {
245  struct pcf50633_rtc *rtc = data;
246 
248  rtc->alarm_pending = 1;
249 }
250 
251 static int __devinit pcf50633_rtc_probe(struct platform_device *pdev)
252 {
253  struct pcf50633_rtc *rtc;
254 
255  rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);
256  if (!rtc)
257  return -ENOMEM;
258 
259  rtc->pcf = dev_to_pcf50633(pdev->dev.parent);
260  platform_set_drvdata(pdev, rtc);
261  rtc->rtc_dev = rtc_device_register("pcf50633-rtc", &pdev->dev,
262  &pcf50633_rtc_ops, THIS_MODULE);
263 
264  if (IS_ERR(rtc->rtc_dev)) {
265  int ret = PTR_ERR(rtc->rtc_dev);
266  kfree(rtc);
267  return ret;
268  }
269 
271  pcf50633_rtc_irq, rtc);
272  return 0;
273 }
274 
275 static int __devexit pcf50633_rtc_remove(struct platform_device *pdev)
276 {
277  struct pcf50633_rtc *rtc;
278 
279  rtc = platform_get_drvdata(pdev);
280 
282 
284  kfree(rtc);
285 
286  return 0;
287 }
288 
289 static struct platform_driver pcf50633_rtc_driver = {
290  .driver = {
291  .name = "pcf50633-rtc",
292  },
293  .probe = pcf50633_rtc_probe,
294  .remove = __devexit_p(pcf50633_rtc_remove),
295 };
296 
297 module_platform_driver(pcf50633_rtc_driver);
298 
299 MODULE_DESCRIPTION("PCF50633 RTC driver");
300 MODULE_AUTHOR("Balaji Rao <[email protected]>");
301 MODULE_LICENSE("GPL");
302