Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
rtc-da9052.c
Go to the documentation of this file.
1 /*
2  * Real time clock driver for DA9052
3  *
4  * Copyright(c) 2012 Dialog Semiconductor Ltd.
5  *
6  * Author: Dajun Dajun Chen <[email protected]>
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 as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  */
14 
15 #include <linux/module.h>
16 #include <linux/platform_device.h>
17 #include <linux/rtc.h>
18 
20 #include <linux/mfd/da9052/reg.h>
21 
22 #define rtc_err(da9052, fmt, ...) \
23  dev_err(da9052->dev, "%s: " fmt, __func__, ##__VA_ARGS__)
24 
25 struct da9052_rtc {
26  struct rtc_device *rtc;
27  struct da9052 *da9052;
28  int irq;
29 };
30 
31 static int da9052_rtc_enable_alarm(struct da9052 *da9052, bool enable)
32 {
33  int ret;
34  if (enable) {
35  ret = da9052_reg_update(da9052, DA9052_ALARM_Y_REG,
38  if (ret != 0)
39  rtc_err(da9052, "Failed to enable ALM: %d\n", ret);
40  } else {
41  ret = da9052_reg_update(da9052, DA9052_ALARM_Y_REG,
43  if (ret != 0)
44  rtc_err(da9052, "Write error: %d\n", ret);
45  }
46  return ret;
47 }
48 
49 static irqreturn_t da9052_rtc_irq(int irq, void *data)
50 {
51  struct da9052_rtc *rtc = data;
52  int ret;
53 
54  ret = da9052_reg_read(rtc->da9052, DA9052_ALARM_MI_REG);
55  if (ret < 0) {
56  rtc_err(rtc->da9052, "Read error: %d\n", ret);
57  return IRQ_NONE;
58  }
59 
60  if (ret & DA9052_ALARMMI_ALARMTYPE) {
61  da9052_rtc_enable_alarm(rtc->da9052, 0);
62  rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF);
63  } else
64  rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_PF);
65 
66  return IRQ_HANDLED;
67 }
68 
69 static int da9052_read_alarm(struct da9052 *da9052, struct rtc_time *rtc_tm)
70 {
71  int ret;
72  uint8_t v[5];
73 
74  ret = da9052_group_read(da9052, DA9052_ALARM_MI_REG, 5, v);
75  if (ret != 0) {
76  rtc_err(da9052, "Failed to group read ALM: %d\n", ret);
77  return ret;
78  }
79 
80  rtc_tm->tm_year = (v[4] & DA9052_RTC_YEAR) + 100;
81  rtc_tm->tm_mon = (v[3] & DA9052_RTC_MONTH) - 1;
82  rtc_tm->tm_mday = v[2] & DA9052_RTC_DAY;
83  rtc_tm->tm_hour = v[1] & DA9052_RTC_HOUR;
84  rtc_tm->tm_min = v[0] & DA9052_RTC_MIN;
85 
86  ret = rtc_valid_tm(rtc_tm);
87  if (ret != 0)
88  return ret;
89  return ret;
90 }
91 
92 static int da9052_set_alarm(struct da9052 *da9052, struct rtc_time *rtc_tm)
93 {
94  int ret;
95  uint8_t v[3];
96 
97  rtc_tm->tm_year -= 100;
98  rtc_tm->tm_mon += 1;
99 
100  ret = da9052_reg_update(da9052, DA9052_ALARM_MI_REG,
101  DA9052_RTC_MIN, rtc_tm->tm_min);
102  if (ret != 0) {
103  rtc_err(da9052, "Failed to write ALRM MIN: %d\n", ret);
104  return ret;
105  }
106 
107  v[0] = rtc_tm->tm_hour;
108  v[1] = rtc_tm->tm_mday;
109  v[2] = rtc_tm->tm_mon;
110 
111  ret = da9052_group_write(da9052, DA9052_ALARM_H_REG, 3, v);
112  if (ret < 0)
113  return ret;
114 
115  ret = da9052_reg_update(da9052, DA9052_ALARM_Y_REG,
116  DA9052_RTC_YEAR, rtc_tm->tm_year);
117  if (ret != 0)
118  rtc_err(da9052, "Failed to write ALRM YEAR: %d\n", ret);
119 
120  return ret;
121 }
122 
123 static int da9052_rtc_get_alarm_status(struct da9052 *da9052)
124 {
125  int ret;
126 
127  ret = da9052_reg_read(da9052, DA9052_ALARM_Y_REG);
128  if (ret < 0) {
129  rtc_err(da9052, "Failed to read ALM: %d\n", ret);
130  return ret;
131  }
133  return (ret > 0) ? 1 : 0;
134 }
135 
136 static int da9052_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm)
137 {
138  struct da9052_rtc *rtc = dev_get_drvdata(dev);
139  uint8_t v[6];
140  int ret;
141 
142  ret = da9052_group_read(rtc->da9052, DA9052_COUNT_S_REG, 6, v);
143  if (ret < 0) {
144  rtc_err(rtc->da9052, "Failed to read RTC time : %d\n", ret);
145  return ret;
146  }
147 
148  rtc_tm->tm_year = (v[5] & DA9052_RTC_YEAR) + 100;
149  rtc_tm->tm_mon = (v[4] & DA9052_RTC_MONTH) - 1;
150  rtc_tm->tm_mday = v[3] & DA9052_RTC_DAY;
151  rtc_tm->tm_hour = v[2] & DA9052_RTC_HOUR;
152  rtc_tm->tm_min = v[1] & DA9052_RTC_MIN;
153  rtc_tm->tm_sec = v[0] & DA9052_RTC_SEC;
154 
155  ret = rtc_valid_tm(rtc_tm);
156  if (ret != 0) {
157  rtc_err(rtc->da9052, "rtc_valid_tm failed: %d\n", ret);
158  return ret;
159  }
160 
161  return 0;
162 }
163 
164 static int da9052_rtc_set_time(struct device *dev, struct rtc_time *tm)
165 {
166  struct da9052_rtc *rtc;
167  uint8_t v[6];
168 
169  rtc = dev_get_drvdata(dev);
170 
171  v[0] = tm->tm_sec;
172  v[1] = tm->tm_min;
173  v[2] = tm->tm_hour;
174  v[3] = tm->tm_mday;
175  v[4] = tm->tm_mon + 1;
176  v[5] = tm->tm_year - 100;
177 
178  return da9052_group_write(rtc->da9052, DA9052_COUNT_S_REG, 6, v);
179 }
180 
181 static int da9052_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
182 {
183  int ret;
184  struct rtc_time *tm = &alrm->time;
185  struct da9052_rtc *rtc = dev_get_drvdata(dev);
186 
187  ret = da9052_read_alarm(rtc->da9052, tm);
188 
189  if (ret)
190  return ret;
191 
192  alrm->enabled = da9052_rtc_get_alarm_status(rtc->da9052);
193 
194  return 0;
195 }
196 
197 static int da9052_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
198 {
199  int ret;
200  struct rtc_time *tm = &alrm->time;
201  struct da9052_rtc *rtc = dev_get_drvdata(dev);
202 
203  ret = da9052_rtc_enable_alarm(rtc->da9052, 0);
204  if (ret < 0)
205  return ret;
206 
207  ret = da9052_set_alarm(rtc->da9052, tm);
208  if (ret)
209  return ret;
210 
211  ret = da9052_rtc_enable_alarm(rtc->da9052, 1);
212 
213  return ret;
214 }
215 
216 static int da9052_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
217 {
218  struct da9052_rtc *rtc = dev_get_drvdata(dev);
219 
220  return da9052_rtc_enable_alarm(rtc->da9052, enabled);
221 }
222 
223 static const struct rtc_class_ops da9052_rtc_ops = {
224  .read_time = da9052_rtc_read_time,
225  .set_time = da9052_rtc_set_time,
226  .read_alarm = da9052_rtc_read_alarm,
227  .set_alarm = da9052_rtc_set_alarm,
228  .alarm_irq_enable = da9052_rtc_alarm_irq_enable,
229 };
230 
231 static int __devinit da9052_rtc_probe(struct platform_device *pdev)
232 {
233  struct da9052_rtc *rtc;
234  int ret;
235 
236  rtc = devm_kzalloc(&pdev->dev, sizeof(struct da9052_rtc), GFP_KERNEL);
237  if (!rtc)
238  return -ENOMEM;
239 
240  rtc->da9052 = dev_get_drvdata(pdev->dev.parent);
241  platform_set_drvdata(pdev, rtc);
242  rtc->irq = platform_get_irq_byname(pdev, "ALM");
243  ret = request_threaded_irq(rtc->irq, NULL, da9052_rtc_irq,
245  "ALM", rtc);
246  if (ret != 0) {
247  rtc_err(rtc->da9052, "irq registration failed: %d\n", ret);
248  return ret;
249  }
250 
251  rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
252  &da9052_rtc_ops, THIS_MODULE);
253  if (IS_ERR(rtc->rtc)) {
254  ret = PTR_ERR(rtc->rtc);
255  goto err_free_irq;
256  }
257 
258  return 0;
259 
260 err_free_irq:
261  free_irq(rtc->irq, rtc);
262  return ret;
263 }
264 
265 static int __devexit da9052_rtc_remove(struct platform_device *pdev)
266 {
267  struct da9052_rtc *rtc = pdev->dev.platform_data;
268 
270  free_irq(rtc->irq, rtc);
271  platform_set_drvdata(pdev, NULL);
272 
273  return 0;
274 }
275 
276 static struct platform_driver da9052_rtc_driver = {
277  .probe = da9052_rtc_probe,
278  .remove = __devexit_p(da9052_rtc_remove),
279  .driver = {
280  .name = "da9052-rtc",
281  .owner = THIS_MODULE,
282  },
283 };
284 
285 module_platform_driver(da9052_rtc_driver);
286 
287 MODULE_AUTHOR("David Dajun Chen <[email protected]>");
288 MODULE_DESCRIPTION("RTC driver for Dialog DA9052 PMIC");
289 MODULE_LICENSE("GPL");
290 MODULE_ALIAS("platform:da9052-rtc");