Merge remote-tracking branch 'asoc/topic/wm8985' into asoc-next
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / rtc / rtc-da9052.c
1 /*
2  * Real time clock driver for DA9052
3  *
4  * Copyright(c) 2012 Dialog Semiconductor Ltd.
5  *
6  * Author: Dajun Dajun Chen <dajun.chen@diasemi.com>
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
19 #include <linux/mfd/da9052/da9052.h>
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,
36                                         DA9052_ALARM_Y_ALARM_ON,
37                                         DA9052_ALARM_Y_ALARM_ON);
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,
42                                         DA9052_ALARM_Y_ALARM_ON, 0);
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         }
132         ret &= DA9052_ALARM_Y_ALARM_ON;
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 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,
244                                    IRQF_TRIGGER_LOW | IRQF_ONESHOT,
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 da9052_rtc_remove(struct platform_device *pdev)
266 {
267         struct da9052_rtc *rtc = pdev->dev.platform_data;
268
269         rtc_device_unregister(rtc->rtc);
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 = 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 <dchen@diasemi.com>");
288 MODULE_DESCRIPTION("RTC driver for Dialog DA9052 PMIC");
289 MODULE_LICENSE("GPL");
290 MODULE_ALIAS("platform:da9052-rtc");