diff options
Diffstat (limited to 'drivers/rtc/rtc-da9052.c')
-rw-r--r-- | drivers/rtc/rtc-da9052.c | 122 |
1 files changed, 66 insertions, 56 deletions
diff --git a/drivers/rtc/rtc-da9052.c b/drivers/rtc/rtc-da9052.c index a1cbf64242a5..e5c9486cf452 100644 --- a/drivers/rtc/rtc-da9052.c +++ b/drivers/rtc/rtc-da9052.c | |||
@@ -20,28 +20,28 @@ | |||
20 | #include <linux/mfd/da9052/da9052.h> | 20 | #include <linux/mfd/da9052/da9052.h> |
21 | #include <linux/mfd/da9052/reg.h> | 21 | #include <linux/mfd/da9052/reg.h> |
22 | 22 | ||
23 | #define rtc_err(da9052, fmt, ...) \ | 23 | #define rtc_err(rtc, fmt, ...) \ |
24 | dev_err(da9052->dev, "%s: " fmt, __func__, ##__VA_ARGS__) | 24 | dev_err(rtc->da9052->dev, "%s: " fmt, __func__, ##__VA_ARGS__) |
25 | 25 | ||
26 | struct da9052_rtc { | 26 | struct da9052_rtc { |
27 | struct rtc_device *rtc; | 27 | struct rtc_device *rtc; |
28 | struct da9052 *da9052; | 28 | struct da9052 *da9052; |
29 | }; | 29 | }; |
30 | 30 | ||
31 | static int da9052_rtc_enable_alarm(struct da9052 *da9052, bool enable) | 31 | static int da9052_rtc_enable_alarm(struct da9052_rtc *rtc, bool enable) |
32 | { | 32 | { |
33 | int ret; | 33 | int ret; |
34 | if (enable) { | 34 | if (enable) { |
35 | ret = da9052_reg_update(da9052, DA9052_ALARM_Y_REG, | 35 | ret = da9052_reg_update(rtc->da9052, DA9052_ALARM_Y_REG, |
36 | DA9052_ALARM_Y_ALARM_ON, | 36 | DA9052_ALARM_Y_ALARM_ON|DA9052_ALARM_Y_TICK_ON, |
37 | DA9052_ALARM_Y_ALARM_ON); | 37 | DA9052_ALARM_Y_ALARM_ON); |
38 | if (ret != 0) | 38 | if (ret != 0) |
39 | rtc_err(da9052, "Failed to enable ALM: %d\n", ret); | 39 | rtc_err(rtc, "Failed to enable ALM: %d\n", ret); |
40 | } else { | 40 | } else { |
41 | ret = da9052_reg_update(da9052, DA9052_ALARM_Y_REG, | 41 | ret = da9052_reg_update(rtc->da9052, DA9052_ALARM_Y_REG, |
42 | DA9052_ALARM_Y_ALARM_ON, 0); | 42 | DA9052_ALARM_Y_ALARM_ON|DA9052_ALARM_Y_TICK_ON, 0); |
43 | if (ret != 0) | 43 | if (ret != 0) |
44 | rtc_err(da9052, "Write error: %d\n", ret); | 44 | rtc_err(rtc, "Write error: %d\n", ret); |
45 | } | 45 | } |
46 | return ret; | 46 | return ret; |
47 | } | 47 | } |
@@ -49,31 +49,20 @@ static int da9052_rtc_enable_alarm(struct da9052 *da9052, bool enable) | |||
49 | static irqreturn_t da9052_rtc_irq(int irq, void *data) | 49 | static irqreturn_t da9052_rtc_irq(int irq, void *data) |
50 | { | 50 | { |
51 | struct da9052_rtc *rtc = data; | 51 | struct da9052_rtc *rtc = data; |
52 | int ret; | ||
53 | 52 | ||
54 | ret = da9052_reg_read(rtc->da9052, DA9052_ALARM_MI_REG); | 53 | rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF); |
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 | 54 | ||
66 | return IRQ_HANDLED; | 55 | return IRQ_HANDLED; |
67 | } | 56 | } |
68 | 57 | ||
69 | static int da9052_read_alarm(struct da9052 *da9052, struct rtc_time *rtc_tm) | 58 | static int da9052_read_alarm(struct da9052_rtc *rtc, struct rtc_time *rtc_tm) |
70 | { | 59 | { |
71 | int ret; | 60 | int ret; |
72 | uint8_t v[5]; | 61 | uint8_t v[5]; |
73 | 62 | ||
74 | ret = da9052_group_read(da9052, DA9052_ALARM_MI_REG, 5, v); | 63 | ret = da9052_group_read(rtc->da9052, DA9052_ALARM_MI_REG, 5, v); |
75 | if (ret != 0) { | 64 | if (ret != 0) { |
76 | rtc_err(da9052, "Failed to group read ALM: %d\n", ret); | 65 | rtc_err(rtc, "Failed to group read ALM: %d\n", ret); |
77 | return ret; | 66 | return ret; |
78 | } | 67 | } |
79 | 68 | ||
@@ -84,23 +73,33 @@ static int da9052_read_alarm(struct da9052 *da9052, struct rtc_time *rtc_tm) | |||
84 | rtc_tm->tm_min = v[0] & DA9052_RTC_MIN; | 73 | rtc_tm->tm_min = v[0] & DA9052_RTC_MIN; |
85 | 74 | ||
86 | ret = rtc_valid_tm(rtc_tm); | 75 | ret = rtc_valid_tm(rtc_tm); |
87 | if (ret != 0) | ||
88 | return ret; | ||
89 | return ret; | 76 | return ret; |
90 | } | 77 | } |
91 | 78 | ||
92 | static int da9052_set_alarm(struct da9052 *da9052, struct rtc_time *rtc_tm) | 79 | static int da9052_set_alarm(struct da9052_rtc *rtc, struct rtc_time *rtc_tm) |
93 | { | 80 | { |
81 | struct da9052 *da9052 = rtc->da9052; | ||
82 | unsigned long alm_time; | ||
94 | int ret; | 83 | int ret; |
95 | uint8_t v[3]; | 84 | uint8_t v[3]; |
96 | 85 | ||
86 | ret = rtc_tm_to_time(rtc_tm, &alm_time); | ||
87 | if (ret != 0) | ||
88 | return ret; | ||
89 | |||
90 | if (rtc_tm->tm_sec > 0) { | ||
91 | alm_time += 60 - rtc_tm->tm_sec; | ||
92 | rtc_time_to_tm(alm_time, rtc_tm); | ||
93 | } | ||
94 | BUG_ON(rtc_tm->tm_sec); /* it will cause repeated irqs if not zero */ | ||
95 | |||
97 | rtc_tm->tm_year -= 100; | 96 | rtc_tm->tm_year -= 100; |
98 | rtc_tm->tm_mon += 1; | 97 | rtc_tm->tm_mon += 1; |
99 | 98 | ||
100 | ret = da9052_reg_update(da9052, DA9052_ALARM_MI_REG, | 99 | ret = da9052_reg_update(da9052, DA9052_ALARM_MI_REG, |
101 | DA9052_RTC_MIN, rtc_tm->tm_min); | 100 | DA9052_RTC_MIN, rtc_tm->tm_min); |
102 | if (ret != 0) { | 101 | if (ret != 0) { |
103 | rtc_err(da9052, "Failed to write ALRM MIN: %d\n", ret); | 102 | rtc_err(rtc, "Failed to write ALRM MIN: %d\n", ret); |
104 | return ret; | 103 | return ret; |
105 | } | 104 | } |
106 | 105 | ||
@@ -115,22 +114,22 @@ static int da9052_set_alarm(struct da9052 *da9052, struct rtc_time *rtc_tm) | |||
115 | ret = da9052_reg_update(da9052, DA9052_ALARM_Y_REG, | 114 | ret = da9052_reg_update(da9052, DA9052_ALARM_Y_REG, |
116 | DA9052_RTC_YEAR, rtc_tm->tm_year); | 115 | DA9052_RTC_YEAR, rtc_tm->tm_year); |
117 | if (ret != 0) | 116 | if (ret != 0) |
118 | rtc_err(da9052, "Failed to write ALRM YEAR: %d\n", ret); | 117 | rtc_err(rtc, "Failed to write ALRM YEAR: %d\n", ret); |
119 | 118 | ||
120 | return ret; | 119 | return ret; |
121 | } | 120 | } |
122 | 121 | ||
123 | static int da9052_rtc_get_alarm_status(struct da9052 *da9052) | 122 | static int da9052_rtc_get_alarm_status(struct da9052_rtc *rtc) |
124 | { | 123 | { |
125 | int ret; | 124 | int ret; |
126 | 125 | ||
127 | ret = da9052_reg_read(da9052, DA9052_ALARM_Y_REG); | 126 | ret = da9052_reg_read(rtc->da9052, DA9052_ALARM_Y_REG); |
128 | if (ret < 0) { | 127 | if (ret < 0) { |
129 | rtc_err(da9052, "Failed to read ALM: %d\n", ret); | 128 | rtc_err(rtc, "Failed to read ALM: %d\n", ret); |
130 | return ret; | 129 | return ret; |
131 | } | 130 | } |
132 | ret &= DA9052_ALARM_Y_ALARM_ON; | 131 | |
133 | return (ret > 0) ? 1 : 0; | 132 | return !!(ret&DA9052_ALARM_Y_ALARM_ON); |
134 | } | 133 | } |
135 | 134 | ||
136 | static int da9052_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm) | 135 | static int da9052_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm) |
@@ -141,7 +140,7 @@ static int da9052_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm) | |||
141 | 140 | ||
142 | ret = da9052_group_read(rtc->da9052, DA9052_COUNT_S_REG, 6, v); | 141 | ret = da9052_group_read(rtc->da9052, DA9052_COUNT_S_REG, 6, v); |
143 | if (ret < 0) { | 142 | if (ret < 0) { |
144 | rtc_err(rtc->da9052, "Failed to read RTC time : %d\n", ret); | 143 | rtc_err(rtc, "Failed to read RTC time : %d\n", ret); |
145 | return ret; | 144 | return ret; |
146 | } | 145 | } |
147 | 146 | ||
@@ -153,18 +152,14 @@ static int da9052_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm) | |||
153 | rtc_tm->tm_sec = v[0] & DA9052_RTC_SEC; | 152 | rtc_tm->tm_sec = v[0] & DA9052_RTC_SEC; |
154 | 153 | ||
155 | ret = rtc_valid_tm(rtc_tm); | 154 | ret = rtc_valid_tm(rtc_tm); |
156 | if (ret != 0) { | 155 | return ret; |
157 | rtc_err(rtc->da9052, "rtc_valid_tm failed: %d\n", ret); | ||
158 | return ret; | ||
159 | } | ||
160 | |||
161 | return 0; | ||
162 | } | 156 | } |
163 | 157 | ||
164 | static int da9052_rtc_set_time(struct device *dev, struct rtc_time *tm) | 158 | static int da9052_rtc_set_time(struct device *dev, struct rtc_time *tm) |
165 | { | 159 | { |
166 | struct da9052_rtc *rtc; | 160 | struct da9052_rtc *rtc; |
167 | uint8_t v[6]; | 161 | uint8_t v[6]; |
162 | int ret; | ||
168 | 163 | ||
169 | rtc = dev_get_drvdata(dev); | 164 | rtc = dev_get_drvdata(dev); |
170 | 165 | ||
@@ -175,7 +170,10 @@ static int da9052_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
175 | v[4] = tm->tm_mon + 1; | 170 | v[4] = tm->tm_mon + 1; |
176 | v[5] = tm->tm_year - 100; | 171 | v[5] = tm->tm_year - 100; |
177 | 172 | ||
178 | return da9052_group_write(rtc->da9052, DA9052_COUNT_S_REG, 6, v); | 173 | ret = da9052_group_write(rtc->da9052, DA9052_COUNT_S_REG, 6, v); |
174 | if (ret < 0) | ||
175 | rtc_err(rtc, "failed to set RTC time: %d\n", ret); | ||
176 | return ret; | ||
179 | } | 177 | } |
180 | 178 | ||
181 | static int da9052_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | 179 | static int da9052_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
@@ -184,13 +182,13 @@ static int da9052_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
184 | struct rtc_time *tm = &alrm->time; | 182 | struct rtc_time *tm = &alrm->time; |
185 | struct da9052_rtc *rtc = dev_get_drvdata(dev); | 183 | struct da9052_rtc *rtc = dev_get_drvdata(dev); |
186 | 184 | ||
187 | ret = da9052_read_alarm(rtc->da9052, tm); | 185 | ret = da9052_read_alarm(rtc, tm); |
188 | 186 | if (ret < 0) { | |
189 | if (ret) | 187 | rtc_err(rtc, "failed to read RTC alarm: %d\n", ret); |
190 | return ret; | 188 | return ret; |
189 | } | ||
191 | 190 | ||
192 | alrm->enabled = da9052_rtc_get_alarm_status(rtc->da9052); | 191 | alrm->enabled = da9052_rtc_get_alarm_status(rtc); |
193 | |||
194 | return 0; | 192 | return 0; |
195 | } | 193 | } |
196 | 194 | ||
@@ -200,16 +198,15 @@ static int da9052_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
200 | struct rtc_time *tm = &alrm->time; | 198 | struct rtc_time *tm = &alrm->time; |
201 | struct da9052_rtc *rtc = dev_get_drvdata(dev); | 199 | struct da9052_rtc *rtc = dev_get_drvdata(dev); |
202 | 200 | ||
203 | ret = da9052_rtc_enable_alarm(rtc->da9052, 0); | 201 | ret = da9052_rtc_enable_alarm(rtc, 0); |
204 | if (ret < 0) | 202 | if (ret < 0) |
205 | return ret; | 203 | return ret; |
206 | 204 | ||
207 | ret = da9052_set_alarm(rtc->da9052, tm); | 205 | ret = da9052_set_alarm(rtc, tm); |
208 | if (ret) | 206 | if (ret < 0) |
209 | return ret; | 207 | return ret; |
210 | 208 | ||
211 | ret = da9052_rtc_enable_alarm(rtc->da9052, 1); | 209 | ret = da9052_rtc_enable_alarm(rtc, 1); |
212 | |||
213 | return ret; | 210 | return ret; |
214 | } | 211 | } |
215 | 212 | ||
@@ -217,7 +214,7 @@ static int da9052_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | |||
217 | { | 214 | { |
218 | struct da9052_rtc *rtc = dev_get_drvdata(dev); | 215 | struct da9052_rtc *rtc = dev_get_drvdata(dev); |
219 | 216 | ||
220 | return da9052_rtc_enable_alarm(rtc->da9052, enabled); | 217 | return da9052_rtc_enable_alarm(rtc, enabled); |
221 | } | 218 | } |
222 | 219 | ||
223 | static const struct rtc_class_ops da9052_rtc_ops = { | 220 | static const struct rtc_class_ops da9052_rtc_ops = { |
@@ -239,10 +236,23 @@ static int da9052_rtc_probe(struct platform_device *pdev) | |||
239 | 236 | ||
240 | rtc->da9052 = dev_get_drvdata(pdev->dev.parent); | 237 | rtc->da9052 = dev_get_drvdata(pdev->dev.parent); |
241 | platform_set_drvdata(pdev, rtc); | 238 | platform_set_drvdata(pdev, rtc); |
239 | |||
240 | ret = da9052_reg_write(rtc->da9052, DA9052_BBAT_CONT_REG, 0xFE); | ||
241 | if (ret < 0) { | ||
242 | rtc_err(rtc, | ||
243 | "Failed to setup RTC battery charging: %d\n", ret); | ||
244 | return ret; | ||
245 | } | ||
246 | |||
247 | ret = da9052_reg_update(rtc->da9052, DA9052_ALARM_Y_REG, | ||
248 | DA9052_ALARM_Y_TICK_ON, 0); | ||
249 | if (ret != 0) | ||
250 | rtc_err(rtc, "Failed to disable TICKS: %d\n", ret); | ||
251 | |||
242 | ret = da9052_request_irq(rtc->da9052, DA9052_IRQ_ALARM, "ALM", | 252 | ret = da9052_request_irq(rtc->da9052, DA9052_IRQ_ALARM, "ALM", |
243 | da9052_rtc_irq, rtc); | 253 | da9052_rtc_irq, rtc); |
244 | if (ret != 0) { | 254 | if (ret != 0) { |
245 | rtc_err(rtc->da9052, "irq registration failed: %d\n", ret); | 255 | rtc_err(rtc, "irq registration failed: %d\n", ret); |
246 | return ret; | 256 | return ret; |
247 | } | 257 | } |
248 | 258 | ||
@@ -261,7 +271,7 @@ static struct platform_driver da9052_rtc_driver = { | |||
261 | 271 | ||
262 | module_platform_driver(da9052_rtc_driver); | 272 | module_platform_driver(da9052_rtc_driver); |
263 | 273 | ||
264 | MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>"); | 274 | MODULE_AUTHOR("Anthony Olech <Anthony.Olech@diasemi.com>"); |
265 | MODULE_DESCRIPTION("RTC driver for Dialog DA9052 PMIC"); | 275 | MODULE_DESCRIPTION("RTC driver for Dialog DA9052 PMIC"); |
266 | MODULE_LICENSE("GPL"); | 276 | MODULE_LICENSE("GPL"); |
267 | MODULE_ALIAS("platform:da9052-rtc"); | 277 | MODULE_ALIAS("platform:da9052-rtc"); |