Commit | Line | Data |
---|---|---|
a4d4121b JMC |
1 | /* |
2 | * RTC driver for Maxim MAX77802 | |
3 | * | |
4 | * Copyright (C) 2013 Google, Inc | |
5 | * | |
6 | * Copyright (C) 2012 Samsung Electronics Co.Ltd | |
7 | * | |
8 | * based on rtc-max8997.c | |
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/slab.h> | |
18 | #include <linux/rtc.h> | |
19 | #include <linux/delay.h> | |
20 | #include <linux/mutex.h> | |
21 | #include <linux/module.h> | |
22 | #include <linux/platform_device.h> | |
23 | #include <linux/mfd/max77686-private.h> | |
24 | #include <linux/irqdomain.h> | |
25 | #include <linux/regmap.h> | |
26 | ||
27 | /* RTC Control Register */ | |
28 | #define BCD_EN_SHIFT 0 | |
29 | #define BCD_EN_MASK (1 << BCD_EN_SHIFT) | |
30 | #define MODEL24_SHIFT 1 | |
31 | #define MODEL24_MASK (1 << MODEL24_SHIFT) | |
32 | /* RTC Update Register1 */ | |
33 | #define RTC_UDR_SHIFT 0 | |
34 | #define RTC_UDR_MASK (1 << RTC_UDR_SHIFT) | |
35 | #define RTC_RBUDR_SHIFT 4 | |
36 | #define RTC_RBUDR_MASK (1 << RTC_RBUDR_SHIFT) | |
37 | /* RTC Hour register */ | |
38 | #define HOUR_PM_SHIFT 6 | |
39 | #define HOUR_PM_MASK (1 << HOUR_PM_SHIFT) | |
40 | /* RTC Alarm Enable */ | |
41 | #define ALARM_ENABLE_SHIFT 7 | |
42 | #define ALARM_ENABLE_MASK (1 << ALARM_ENABLE_SHIFT) | |
43 | ||
44 | /* For the RTCAE1 register, we write this value to enable the alarm */ | |
45 | #define ALARM_ENABLE_VALUE 0x77 | |
46 | ||
47 | #define MAX77802_RTC_UPDATE_DELAY_US 200 | |
48 | ||
49 | enum { | |
50 | RTC_SEC = 0, | |
51 | RTC_MIN, | |
52 | RTC_HOUR, | |
53 | RTC_WEEKDAY, | |
54 | RTC_MONTH, | |
55 | RTC_YEAR, | |
56 | RTC_DATE, | |
57 | RTC_NR_TIME | |
58 | }; | |
59 | ||
60 | struct max77802_rtc_info { | |
61 | struct device *dev; | |
62 | struct max77686_dev *max77802; | |
63 | struct i2c_client *rtc; | |
64 | struct rtc_device *rtc_dev; | |
65 | struct mutex lock; | |
66 | ||
67 | struct regmap *regmap; | |
68 | ||
69 | int virq; | |
70 | int rtc_24hr_mode; | |
71 | }; | |
72 | ||
73 | enum MAX77802_RTC_OP { | |
74 | MAX77802_RTC_WRITE, | |
75 | MAX77802_RTC_READ, | |
76 | }; | |
77 | ||
78 | static void max77802_rtc_data_to_tm(u8 *data, struct rtc_time *tm, | |
79 | int rtc_24hr_mode) | |
80 | { | |
81 | tm->tm_sec = data[RTC_SEC] & 0xff; | |
82 | tm->tm_min = data[RTC_MIN] & 0xff; | |
83 | if (rtc_24hr_mode) | |
84 | tm->tm_hour = data[RTC_HOUR] & 0x1f; | |
85 | else { | |
86 | tm->tm_hour = data[RTC_HOUR] & 0x0f; | |
87 | if (data[RTC_HOUR] & HOUR_PM_MASK) | |
88 | tm->tm_hour += 12; | |
89 | } | |
90 | ||
91 | /* Only a single bit is set in data[], so fls() would be equivalent */ | |
92 | tm->tm_wday = ffs(data[RTC_WEEKDAY] & 0xff) - 1; | |
93 | tm->tm_mday = data[RTC_DATE] & 0x1f; | |
94 | tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1; | |
95 | ||
96 | tm->tm_year = data[RTC_YEAR] & 0xff; | |
97 | tm->tm_yday = 0; | |
98 | tm->tm_isdst = 0; | |
99 | } | |
100 | ||
101 | static int max77802_rtc_tm_to_data(struct rtc_time *tm, u8 *data) | |
102 | { | |
103 | data[RTC_SEC] = tm->tm_sec; | |
104 | data[RTC_MIN] = tm->tm_min; | |
105 | data[RTC_HOUR] = tm->tm_hour; | |
106 | data[RTC_WEEKDAY] = 1 << tm->tm_wday; | |
107 | data[RTC_DATE] = tm->tm_mday; | |
108 | data[RTC_MONTH] = tm->tm_mon + 1; | |
109 | data[RTC_YEAR] = tm->tm_year; | |
110 | ||
111 | return 0; | |
112 | } | |
113 | ||
114 | static int max77802_rtc_update(struct max77802_rtc_info *info, | |
115 | enum MAX77802_RTC_OP op) | |
116 | { | |
117 | int ret; | |
118 | unsigned int data; | |
119 | ||
120 | if (op == MAX77802_RTC_WRITE) | |
121 | data = 1 << RTC_UDR_SHIFT; | |
122 | else | |
123 | data = 1 << RTC_RBUDR_SHIFT; | |
124 | ||
125 | ret = regmap_update_bits(info->max77802->regmap, | |
126 | MAX77802_RTC_UPDATE0, data, data); | |
127 | if (ret < 0) | |
128 | dev_err(info->dev, "%s: fail to write update reg(ret=%d, data=0x%x)\n", | |
129 | __func__, ret, data); | |
130 | else { | |
131 | /* Minimum delay required before RTC update. */ | |
132 | usleep_range(MAX77802_RTC_UPDATE_DELAY_US, | |
133 | MAX77802_RTC_UPDATE_DELAY_US * 2); | |
134 | } | |
135 | ||
136 | return ret; | |
137 | } | |
138 | ||
139 | static int max77802_rtc_read_time(struct device *dev, struct rtc_time *tm) | |
140 | { | |
141 | struct max77802_rtc_info *info = dev_get_drvdata(dev); | |
142 | u8 data[RTC_NR_TIME]; | |
143 | int ret; | |
144 | ||
145 | mutex_lock(&info->lock); | |
146 | ||
147 | ret = max77802_rtc_update(info, MAX77802_RTC_READ); | |
148 | if (ret < 0) | |
149 | goto out; | |
150 | ||
151 | ret = regmap_bulk_read(info->max77802->regmap, | |
152 | MAX77802_RTC_SEC, data, RTC_NR_TIME); | |
153 | if (ret < 0) { | |
154 | dev_err(info->dev, "%s: fail to read time reg(%d)\n", __func__, | |
155 | ret); | |
156 | goto out; | |
157 | } | |
158 | ||
159 | max77802_rtc_data_to_tm(data, tm, info->rtc_24hr_mode); | |
160 | ||
161 | ret = rtc_valid_tm(tm); | |
162 | ||
163 | out: | |
164 | mutex_unlock(&info->lock); | |
165 | return ret; | |
166 | } | |
167 | ||
168 | static int max77802_rtc_set_time(struct device *dev, struct rtc_time *tm) | |
169 | { | |
170 | struct max77802_rtc_info *info = dev_get_drvdata(dev); | |
171 | u8 data[RTC_NR_TIME]; | |
172 | int ret; | |
173 | ||
174 | ret = max77802_rtc_tm_to_data(tm, data); | |
175 | if (ret < 0) | |
176 | return ret; | |
177 | ||
178 | mutex_lock(&info->lock); | |
179 | ||
180 | ret = regmap_bulk_write(info->max77802->regmap, | |
181 | MAX77802_RTC_SEC, data, RTC_NR_TIME); | |
182 | if (ret < 0) { | |
183 | dev_err(info->dev, "%s: fail to write time reg(%d)\n", __func__, | |
184 | ret); | |
185 | goto out; | |
186 | } | |
187 | ||
188 | ret = max77802_rtc_update(info, MAX77802_RTC_WRITE); | |
189 | ||
190 | out: | |
191 | mutex_unlock(&info->lock); | |
192 | return ret; | |
193 | } | |
194 | ||
195 | static int max77802_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |
196 | { | |
197 | struct max77802_rtc_info *info = dev_get_drvdata(dev); | |
198 | u8 data[RTC_NR_TIME]; | |
199 | unsigned int val; | |
200 | int ret; | |
201 | ||
202 | mutex_lock(&info->lock); | |
203 | ||
204 | ret = max77802_rtc_update(info, MAX77802_RTC_READ); | |
205 | if (ret < 0) | |
206 | goto out; | |
207 | ||
208 | ret = regmap_bulk_read(info->max77802->regmap, | |
209 | MAX77802_ALARM1_SEC, data, RTC_NR_TIME); | |
210 | if (ret < 0) { | |
211 | dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n", | |
212 | __func__, __LINE__, ret); | |
213 | goto out; | |
214 | } | |
215 | ||
216 | max77802_rtc_data_to_tm(data, &alrm->time, info->rtc_24hr_mode); | |
217 | ||
218 | alrm->enabled = 0; | |
219 | ret = regmap_read(info->max77802->regmap, | |
220 | MAX77802_RTC_AE1, &val); | |
221 | if (ret < 0) { | |
222 | dev_err(info->dev, "%s:%d fail to read alarm enable(%d)\n", | |
223 | __func__, __LINE__, ret); | |
224 | goto out; | |
225 | } | |
226 | if (val) | |
227 | alrm->enabled = 1; | |
228 | ||
229 | alrm->pending = 0; | |
230 | ret = regmap_read(info->max77802->regmap, MAX77802_REG_STATUS2, &val); | |
231 | if (ret < 0) { | |
232 | dev_err(info->dev, "%s:%d fail to read status2 reg(%d)\n", | |
233 | __func__, __LINE__, ret); | |
234 | goto out; | |
235 | } | |
236 | ||
237 | if (val & (1 << 2)) /* RTCA1 */ | |
238 | alrm->pending = 1; | |
239 | ||
240 | out: | |
241 | mutex_unlock(&info->lock); | |
242 | return 0; | |
243 | } | |
244 | ||
245 | static int max77802_rtc_stop_alarm(struct max77802_rtc_info *info) | |
246 | { | |
247 | int ret; | |
248 | ||
249 | if (!mutex_is_locked(&info->lock)) | |
250 | dev_warn(info->dev, "%s: should have mutex locked\n", __func__); | |
251 | ||
252 | ret = max77802_rtc_update(info, MAX77802_RTC_READ); | |
253 | if (ret < 0) | |
254 | goto out; | |
255 | ||
256 | ret = regmap_write(info->max77802->regmap, | |
257 | MAX77802_RTC_AE1, 0); | |
258 | if (ret < 0) { | |
259 | dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", | |
260 | __func__, ret); | |
261 | goto out; | |
262 | } | |
263 | ||
264 | ret = max77802_rtc_update(info, MAX77802_RTC_WRITE); | |
265 | out: | |
266 | return ret; | |
267 | } | |
268 | ||
269 | static int max77802_rtc_start_alarm(struct max77802_rtc_info *info) | |
270 | { | |
271 | int ret; | |
272 | ||
273 | if (!mutex_is_locked(&info->lock)) | |
274 | dev_warn(info->dev, "%s: should have mutex locked\n", | |
275 | __func__); | |
276 | ||
277 | ret = max77802_rtc_update(info, MAX77802_RTC_READ); | |
278 | if (ret < 0) | |
279 | goto out; | |
280 | ||
281 | ret = regmap_write(info->max77802->regmap, | |
282 | MAX77802_RTC_AE1, | |
283 | ALARM_ENABLE_VALUE); | |
284 | ||
285 | if (ret < 0) { | |
286 | dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", | |
287 | __func__, ret); | |
288 | goto out; | |
289 | } | |
290 | ||
291 | ret = max77802_rtc_update(info, MAX77802_RTC_WRITE); | |
292 | out: | |
293 | return ret; | |
294 | } | |
295 | ||
296 | static int max77802_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |
297 | { | |
298 | struct max77802_rtc_info *info = dev_get_drvdata(dev); | |
299 | u8 data[RTC_NR_TIME]; | |
300 | int ret; | |
301 | ||
302 | ret = max77802_rtc_tm_to_data(&alrm->time, data); | |
303 | if (ret < 0) | |
304 | return ret; | |
305 | ||
306 | mutex_lock(&info->lock); | |
307 | ||
308 | ret = max77802_rtc_stop_alarm(info); | |
309 | if (ret < 0) | |
310 | goto out; | |
311 | ||
312 | ret = regmap_bulk_write(info->max77802->regmap, | |
313 | MAX77802_ALARM1_SEC, data, RTC_NR_TIME); | |
314 | ||
315 | if (ret < 0) { | |
316 | dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", | |
317 | __func__, ret); | |
318 | goto out; | |
319 | } | |
320 | ||
321 | ret = max77802_rtc_update(info, MAX77802_RTC_WRITE); | |
322 | if (ret < 0) | |
323 | goto out; | |
324 | ||
325 | if (alrm->enabled) | |
326 | ret = max77802_rtc_start_alarm(info); | |
327 | out: | |
328 | mutex_unlock(&info->lock); | |
329 | return ret; | |
330 | } | |
331 | ||
332 | static int max77802_rtc_alarm_irq_enable(struct device *dev, | |
333 | unsigned int enabled) | |
334 | { | |
335 | struct max77802_rtc_info *info = dev_get_drvdata(dev); | |
336 | int ret; | |
337 | ||
338 | mutex_lock(&info->lock); | |
339 | if (enabled) | |
340 | ret = max77802_rtc_start_alarm(info); | |
341 | else | |
342 | ret = max77802_rtc_stop_alarm(info); | |
343 | mutex_unlock(&info->lock); | |
344 | ||
345 | return ret; | |
346 | } | |
347 | ||
348 | static irqreturn_t max77802_rtc_alarm_irq(int irq, void *data) | |
349 | { | |
350 | struct max77802_rtc_info *info = data; | |
351 | ||
352 | dev_dbg(info->dev, "%s:irq(%d)\n", __func__, irq); | |
353 | ||
354 | rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF); | |
355 | ||
356 | return IRQ_HANDLED; | |
357 | } | |
358 | ||
359 | static const struct rtc_class_ops max77802_rtc_ops = { | |
360 | .read_time = max77802_rtc_read_time, | |
361 | .set_time = max77802_rtc_set_time, | |
362 | .read_alarm = max77802_rtc_read_alarm, | |
363 | .set_alarm = max77802_rtc_set_alarm, | |
364 | .alarm_irq_enable = max77802_rtc_alarm_irq_enable, | |
365 | }; | |
366 | ||
367 | static int max77802_rtc_init_reg(struct max77802_rtc_info *info) | |
368 | { | |
369 | u8 data[2]; | |
370 | int ret; | |
371 | ||
372 | max77802_rtc_update(info, MAX77802_RTC_READ); | |
373 | ||
374 | /* Set RTC control register : Binary mode, 24hour mdoe */ | |
375 | data[0] = (1 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT); | |
376 | data[1] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT); | |
377 | ||
378 | info->rtc_24hr_mode = 1; | |
379 | ||
380 | ret = regmap_bulk_write(info->max77802->regmap, | |
381 | MAX77802_RTC_CONTROLM, data, ARRAY_SIZE(data)); | |
382 | if (ret < 0) { | |
383 | dev_err(info->dev, "%s: fail to write controlm reg(%d)\n", | |
384 | __func__, ret); | |
385 | return ret; | |
386 | } | |
387 | ||
388 | ret = max77802_rtc_update(info, MAX77802_RTC_WRITE); | |
389 | return ret; | |
390 | } | |
391 | ||
392 | static int max77802_rtc_probe(struct platform_device *pdev) | |
393 | { | |
394 | struct max77686_dev *max77802 = dev_get_drvdata(pdev->dev.parent); | |
395 | struct max77802_rtc_info *info; | |
396 | int ret; | |
397 | ||
398 | dev_dbg(&pdev->dev, "%s\n", __func__); | |
399 | ||
400 | info = devm_kzalloc(&pdev->dev, sizeof(struct max77802_rtc_info), | |
401 | GFP_KERNEL); | |
402 | if (!info) | |
403 | return -ENOMEM; | |
404 | ||
405 | mutex_init(&info->lock); | |
406 | info->dev = &pdev->dev; | |
407 | info->max77802 = max77802; | |
408 | info->rtc = max77802->i2c; | |
409 | ||
410 | platform_set_drvdata(pdev, info); | |
411 | ||
412 | ret = max77802_rtc_init_reg(info); | |
413 | ||
414 | if (ret < 0) { | |
415 | dev_err(&pdev->dev, "Failed to initialize RTC reg:%d\n", ret); | |
416 | return ret; | |
417 | } | |
418 | ||
419 | device_init_wakeup(&pdev->dev, 1); | |
420 | ||
421 | info->rtc_dev = devm_rtc_device_register(&pdev->dev, "max77802-rtc", | |
422 | &max77802_rtc_ops, THIS_MODULE); | |
423 | ||
424 | if (IS_ERR(info->rtc_dev)) { | |
425 | ret = PTR_ERR(info->rtc_dev); | |
426 | dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); | |
427 | if (ret == 0) | |
428 | ret = -EINVAL; | |
429 | return ret; | |
430 | } | |
431 | ||
432 | if (!max77802->rtc_irq_data) { | |
433 | dev_err(&pdev->dev, "No RTC regmap IRQ chip\n"); | |
434 | return -EINVAL; | |
435 | } | |
436 | ||
437 | info->virq = regmap_irq_get_virq(max77802->rtc_irq_data, | |
438 | MAX77686_RTCIRQ_RTCA1); | |
439 | ||
440 | if (info->virq <= 0) { | |
441 | dev_err(&pdev->dev, "Failed to get virtual IRQ %d\n", | |
442 | MAX77686_RTCIRQ_RTCA1); | |
443 | return -EINVAL; | |
444 | } | |
445 | ||
446 | ret = devm_request_threaded_irq(&pdev->dev, info->virq, NULL, | |
447 | max77802_rtc_alarm_irq, 0, "rtc-alarm1", | |
448 | info); | |
449 | if (ret < 0) | |
450 | dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", | |
451 | info->virq, ret); | |
452 | ||
453 | return ret; | |
454 | } | |
455 | ||
456 | #ifdef CONFIG_PM_SLEEP | |
457 | static int max77802_rtc_suspend(struct device *dev) | |
458 | { | |
459 | if (device_may_wakeup(dev)) { | |
460 | struct max77802_rtc_info *info = dev_get_drvdata(dev); | |
461 | ||
462 | return enable_irq_wake(info->virq); | |
463 | } | |
464 | ||
465 | return 0; | |
466 | } | |
467 | ||
468 | static int max77802_rtc_resume(struct device *dev) | |
469 | { | |
470 | if (device_may_wakeup(dev)) { | |
471 | struct max77802_rtc_info *info = dev_get_drvdata(dev); | |
472 | ||
473 | return disable_irq_wake(info->virq); | |
474 | } | |
475 | ||
476 | return 0; | |
477 | } | |
478 | #endif | |
479 | ||
480 | static SIMPLE_DEV_PM_OPS(max77802_rtc_pm_ops, | |
481 | max77802_rtc_suspend, max77802_rtc_resume); | |
482 | ||
483 | static const struct platform_device_id rtc_id[] = { | |
484 | { "max77802-rtc", 0 }, | |
485 | {}, | |
486 | }; | |
9bde31df | 487 | MODULE_DEVICE_TABLE(platform, rtc_id); |
a4d4121b JMC |
488 | |
489 | static struct platform_driver max77802_rtc_driver = { | |
490 | .driver = { | |
491 | .name = "max77802-rtc", | |
a4d4121b JMC |
492 | .pm = &max77802_rtc_pm_ops, |
493 | }, | |
494 | .probe = max77802_rtc_probe, | |
495 | .id_table = rtc_id, | |
496 | }; | |
497 | ||
498 | module_platform_driver(max77802_rtc_driver); | |
499 | ||
500 | MODULE_DESCRIPTION("Maxim MAX77802 RTC driver"); | |
501 | MODULE_AUTHOR("Simon Glass <sjg@chromium.org>"); | |
502 | MODULE_LICENSE("GPL"); |