Version:  2.0.40 2.2.26 2.4.37 2.6.39 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15

Linux/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 #include <linux/err.h>
 19 
 20 #include <linux/mfd/da9052/da9052.h>
 21 #include <linux/mfd/da9052/reg.h>
 22 
 23 #define rtc_err(da9052, fmt, ...) \
 24                 dev_err(da9052->dev, "%s: " fmt, __func__, ##__VA_ARGS__)
 25 
 26 struct da9052_rtc {
 27         struct rtc_device *rtc;
 28         struct da9052 *da9052;
 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         ret = da9052_request_irq(rtc->da9052, DA9052_IRQ_ALARM, "ALM",
243                                 da9052_rtc_irq, rtc);
244         if (ret != 0) {
245                 rtc_err(rtc->da9052, "irq registration failed: %d\n", ret);
246                 return ret;
247         }
248 
249         rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
250                                        &da9052_rtc_ops, THIS_MODULE);
251         return PTR_ERR_OR_ZERO(rtc->rtc);
252 }
253 
254 static struct platform_driver da9052_rtc_driver = {
255         .probe  = da9052_rtc_probe,
256         .driver = {
257                 .name   = "da9052-rtc",
258                 .owner  = THIS_MODULE,
259         },
260 };
261 
262 module_platform_driver(da9052_rtc_driver);
263 
264 MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
265 MODULE_DESCRIPTION("RTC driver for Dialog DA9052 PMIC");
266 MODULE_LICENSE("GPL");
267 MODULE_ALIAS("platform:da9052-rtc");
268 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us