1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Real time clock driver for DA9055
5 * Copyright(c) 2012 Dialog Semiconductor Ltd.
7 * Author: Dajun Dajun Chen <dajun.chen@diasemi.com>
10 #include <linux/module.h>
11 #include <linux/platform_device.h>
12 #include <linux/rtc.h>
14 #include <linux/mfd/da9055/core.h>
15 #include <linux/mfd/da9055/reg.h>
16 #include <linux/mfd/da9055/pdata.h>
19 struct rtc_device
*rtc
;
20 struct da9055
*da9055
;
24 static int da9055_rtc_enable_alarm(struct da9055_rtc
*rtc
, bool enable
)
28 ret
= da9055_reg_update(rtc
->da9055
, DA9055_REG_ALARM_Y
,
32 dev_err(rtc
->da9055
->dev
, "Failed to enable ALM: %d\n",
34 rtc
->alarm_enable
= 1;
36 ret
= da9055_reg_update(rtc
->da9055
, DA9055_REG_ALARM_Y
,
37 DA9055_RTC_ALM_EN
, 0);
39 dev_err(rtc
->da9055
->dev
,
40 "Failed to disable ALM: %d\n", ret
);
41 rtc
->alarm_enable
= 0;
46 static irqreturn_t
da9055_rtc_alm_irq(int irq
, void *data
)
48 struct da9055_rtc
*rtc
= data
;
50 da9055_rtc_enable_alarm(rtc
, 0);
51 rtc_update_irq(rtc
->rtc
, 1, RTC_IRQF
| RTC_AF
);
56 static int da9055_read_alarm(struct da9055
*da9055
, struct rtc_time
*rtc_tm
)
61 ret
= da9055_group_read(da9055
, DA9055_REG_ALARM_MI
, 5, v
);
63 dev_err(da9055
->dev
, "Failed to group read ALM: %d\n", ret
);
67 rtc_tm
->tm_year
= (v
[4] & DA9055_RTC_ALM_YEAR
) + 100;
68 rtc_tm
->tm_mon
= (v
[3] & DA9055_RTC_ALM_MONTH
) - 1;
69 rtc_tm
->tm_mday
= v
[2] & DA9055_RTC_ALM_DAY
;
70 rtc_tm
->tm_hour
= v
[1] & DA9055_RTC_ALM_HOUR
;
71 rtc_tm
->tm_min
= v
[0] & DA9055_RTC_ALM_MIN
;
74 return rtc_valid_tm(rtc_tm
);
77 static int da9055_set_alarm(struct da9055
*da9055
, struct rtc_time
*rtc_tm
)
82 rtc_tm
->tm_year
-= 100;
85 ret
= da9055_reg_update(da9055
, DA9055_REG_ALARM_MI
,
86 DA9055_RTC_ALM_MIN
, rtc_tm
->tm_min
);
88 dev_err(da9055
->dev
, "Failed to write ALRM MIN: %d\n", ret
);
92 v
[0] = rtc_tm
->tm_hour
;
93 v
[1] = rtc_tm
->tm_mday
;
95 ret
= da9055_group_write(da9055
, DA9055_REG_ALARM_H
, 2, v
);
99 ret
= da9055_reg_update(da9055
, DA9055_REG_ALARM_MO
,
100 DA9055_RTC_ALM_MONTH
, rtc_tm
->tm_mon
);
102 dev_err(da9055
->dev
, "Failed to write ALM Month:%d\n", ret
);
104 ret
= da9055_reg_update(da9055
, DA9055_REG_ALARM_Y
,
105 DA9055_RTC_ALM_YEAR
, rtc_tm
->tm_year
);
107 dev_err(da9055
->dev
, "Failed to write ALM Year:%d\n", ret
);
112 static int da9055_rtc_get_alarm_status(struct da9055
*da9055
)
116 ret
= da9055_reg_read(da9055
, DA9055_REG_ALARM_Y
);
118 dev_err(da9055
->dev
, "Failed to read ALM: %d\n", ret
);
121 ret
&= DA9055_RTC_ALM_EN
;
122 return (ret
> 0) ? 1 : 0;
125 static int da9055_rtc_read_time(struct device
*dev
, struct rtc_time
*rtc_tm
)
127 struct da9055_rtc
*rtc
= dev_get_drvdata(dev
);
131 ret
= da9055_reg_read(rtc
->da9055
, DA9055_REG_COUNT_S
);
136 * Registers are only valid when RTC_READ
137 * status bit is asserted
139 if (!(ret
& DA9055_RTC_READ
))
142 ret
= da9055_group_read(rtc
->da9055
, DA9055_REG_COUNT_S
, 6, v
);
144 dev_err(rtc
->da9055
->dev
, "Failed to read RTC time : %d\n",
149 rtc_tm
->tm_year
= (v
[5] & DA9055_RTC_YEAR
) + 100;
150 rtc_tm
->tm_mon
= (v
[4] & DA9055_RTC_MONTH
) - 1;
151 rtc_tm
->tm_mday
= v
[3] & DA9055_RTC_DAY
;
152 rtc_tm
->tm_hour
= v
[2] & DA9055_RTC_HOUR
;
153 rtc_tm
->tm_min
= v
[1] & DA9055_RTC_MIN
;
154 rtc_tm
->tm_sec
= v
[0] & DA9055_RTC_SEC
;
159 static int da9055_rtc_set_time(struct device
*dev
, struct rtc_time
*tm
)
161 struct da9055_rtc
*rtc
;
164 rtc
= dev_get_drvdata(dev
);
170 v
[4] = tm
->tm_mon
+ 1;
171 v
[5] = tm
->tm_year
- 100;
173 return da9055_group_write(rtc
->da9055
, DA9055_REG_COUNT_S
, 6, v
);
176 static int da9055_rtc_read_alarm(struct device
*dev
, struct rtc_wkalrm
*alrm
)
179 struct rtc_time
*tm
= &alrm
->time
;
180 struct da9055_rtc
*rtc
= dev_get_drvdata(dev
);
182 ret
= da9055_read_alarm(rtc
->da9055
, tm
);
187 alrm
->enabled
= da9055_rtc_get_alarm_status(rtc
->da9055
);
192 static int da9055_rtc_set_alarm(struct device
*dev
, struct rtc_wkalrm
*alrm
)
195 struct rtc_time
*tm
= &alrm
->time
;
196 struct da9055_rtc
*rtc
= dev_get_drvdata(dev
);
198 ret
= da9055_rtc_enable_alarm(rtc
, 0);
202 ret
= da9055_set_alarm(rtc
->da9055
, tm
);
206 ret
= da9055_rtc_enable_alarm(rtc
, 1);
211 static int da9055_rtc_alarm_irq_enable(struct device
*dev
, unsigned int enabled
)
213 struct da9055_rtc
*rtc
= dev_get_drvdata(dev
);
215 return da9055_rtc_enable_alarm(rtc
, enabled
);
218 static const struct rtc_class_ops da9055_rtc_ops
= {
219 .read_time
= da9055_rtc_read_time
,
220 .set_time
= da9055_rtc_set_time
,
221 .read_alarm
= da9055_rtc_read_alarm
,
222 .set_alarm
= da9055_rtc_set_alarm
,
223 .alarm_irq_enable
= da9055_rtc_alarm_irq_enable
,
226 static int da9055_rtc_device_init(struct da9055
*da9055
,
227 struct da9055_pdata
*pdata
)
231 /* Enable RTC and the internal Crystal */
232 ret
= da9055_reg_update(da9055
, DA9055_REG_CONTROL_B
,
233 DA9055_RTC_EN
, DA9055_RTC_EN
);
236 ret
= da9055_reg_update(da9055
, DA9055_REG_EN_32K
,
237 DA9055_CRYSTAL_EN
, DA9055_CRYSTAL_EN
);
241 /* Enable RTC in Power Down mode */
242 ret
= da9055_reg_update(da9055
, DA9055_REG_CONTROL_B
,
243 DA9055_RTC_MODE_PD
, DA9055_RTC_MODE_PD
);
247 /* Enable RTC in Reset mode */
248 if (pdata
&& pdata
->reset_enable
) {
249 ret
= da9055_reg_update(da9055
, DA9055_REG_CONTROL_B
,
251 DA9055_RTC_MODE_SD
<<
252 DA9055_RTC_MODE_SD_SHIFT
);
257 /* Disable the RTC TICK ALM */
258 ret
= da9055_reg_update(da9055
, DA9055_REG_ALARM_MO
,
259 DA9055_RTC_TICK_WAKE_MASK
, 0);
266 static int da9055_rtc_probe(struct platform_device
*pdev
)
268 struct da9055_rtc
*rtc
;
269 struct da9055_pdata
*pdata
= NULL
;
272 rtc
= devm_kzalloc(&pdev
->dev
, sizeof(struct da9055_rtc
), GFP_KERNEL
);
276 rtc
->da9055
= dev_get_drvdata(pdev
->dev
.parent
);
277 pdata
= dev_get_platdata(rtc
->da9055
->dev
);
278 platform_set_drvdata(pdev
, rtc
);
280 ret
= da9055_rtc_device_init(rtc
->da9055
, pdata
);
284 ret
= da9055_reg_read(rtc
->da9055
, DA9055_REG_ALARM_Y
);
288 if (ret
& DA9055_RTC_ALM_EN
)
289 rtc
->alarm_enable
= 1;
291 device_init_wakeup(&pdev
->dev
, 1);
293 rtc
->rtc
= devm_rtc_device_register(&pdev
->dev
, pdev
->name
,
294 &da9055_rtc_ops
, THIS_MODULE
);
295 if (IS_ERR(rtc
->rtc
)) {
296 ret
= PTR_ERR(rtc
->rtc
);
300 alm_irq
= platform_get_irq_byname(pdev
, "ALM");
304 ret
= devm_request_threaded_irq(&pdev
->dev
, alm_irq
, NULL
,
306 IRQF_TRIGGER_HIGH
| IRQF_ONESHOT
,
309 dev_err(rtc
->da9055
->dev
, "irq registration failed: %d\n", ret
);
317 /* Turn off the alarm if it should not be a wake source. */
318 static int da9055_rtc_suspend(struct device
*dev
)
320 struct platform_device
*pdev
= to_platform_device(dev
);
321 struct da9055_rtc
*rtc
= dev_get_drvdata(&pdev
->dev
);
324 if (!device_may_wakeup(&pdev
->dev
)) {
325 /* Disable the ALM IRQ */
326 ret
= da9055_rtc_enable_alarm(rtc
, 0);
328 dev_err(&pdev
->dev
, "Failed to disable RTC ALM\n");
334 /* Enable the alarm if it should be enabled (in case it was disabled to
335 * prevent use as a wake source).
337 static int da9055_rtc_resume(struct device
*dev
)
339 struct platform_device
*pdev
= to_platform_device(dev
);
340 struct da9055_rtc
*rtc
= dev_get_drvdata(&pdev
->dev
);
343 if (!device_may_wakeup(&pdev
->dev
)) {
344 if (rtc
->alarm_enable
) {
345 ret
= da9055_rtc_enable_alarm(rtc
, 1);
348 "Failed to restart RTC ALM\n");
355 /* Unconditionally disable the alarm */
356 static int da9055_rtc_freeze(struct device
*dev
)
358 struct platform_device
*pdev
= to_platform_device(dev
);
359 struct da9055_rtc
*rtc
= dev_get_drvdata(&pdev
->dev
);
362 ret
= da9055_rtc_enable_alarm(rtc
, 0);
364 dev_err(&pdev
->dev
, "Failed to freeze RTC ALMs\n");
370 #define da9055_rtc_suspend NULL
371 #define da9055_rtc_resume NULL
372 #define da9055_rtc_freeze NULL
375 static const struct dev_pm_ops da9055_rtc_pm_ops
= {
376 .suspend
= da9055_rtc_suspend
,
377 .resume
= da9055_rtc_resume
,
379 .freeze
= da9055_rtc_freeze
,
380 .thaw
= da9055_rtc_resume
,
381 .restore
= da9055_rtc_resume
,
383 .poweroff
= da9055_rtc_suspend
,
386 static struct platform_driver da9055_rtc_driver
= {
387 .probe
= da9055_rtc_probe
,
389 .name
= "da9055-rtc",
390 .pm
= &da9055_rtc_pm_ops
,
394 module_platform_driver(da9055_rtc_driver
);
396 MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
397 MODULE_DESCRIPTION("RTC driver for Dialog DA9055 PMIC");
398 MODULE_LICENSE("GPL");
399 MODULE_ALIAS("platform:da9055-rtc");