Skip to content

Commit e641808

Browse files
andredalexandrebelloni
authored andcommitted
rtc: s5m: add support for S2MPG10 RTC
Add support for Samsung's S2MPG10 PMIC RTC, which is similar to the existing PMIC RTCs supported by this driver. S2MPG10 doesn't use I2C, so we expect the core driver to have created a regmap for us. Additionally, it can be used for doing a cold-reset. If requested to do so (via DT), S2MPG10 is programmed with a watchdog configuration that will perform a full power cycle upon watchdog expiry. Reviewed-by: Krzysztof Kozlowski <[email protected]> Signed-off-by: André Draszik <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexandre Belloni <[email protected]>
1 parent a57743b commit e641808

File tree

1 file changed

+60
-0
lines changed

1 file changed

+60
-0
lines changed

drivers/rtc/rtc-s5m.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <linux/module.h>
1111
#include <linux/i2c.h>
1212
#include <linux/bcd.h>
13+
#include <linux/reboot.h>
1314
#include <linux/regmap.h>
1415
#include <linux/rtc.h>
1516
#include <linux/platform_device.h>
@@ -53,6 +54,7 @@ enum {
5354
* Device | Write time | Read time | Write alarm
5455
* =================================================
5556
* S5M8767 | UDR + TIME | | UDR
57+
* S2MPG10 | WUDR | RUDR | AUDR
5658
* S2MPS11/14 | WUDR | RUDR | WUDR + RUDR
5759
* S2MPS13 | WUDR | RUDR | WUDR + AUDR
5860
* S2MPS15 | WUDR | RUDR | AUDR
@@ -99,6 +101,20 @@ static const struct s5m_rtc_reg_config s5m_rtc_regs = {
99101
.write_alarm_udr_mask = S5M_RTC_UDR_MASK,
100102
};
101103

104+
/* Register map for S2MPG10 */
105+
static const struct s5m_rtc_reg_config s2mpg10_rtc_regs = {
106+
.regs_count = 7,
107+
.time = S2MPG10_RTC_SEC,
108+
.ctrl = S2MPG10_RTC_CTRL,
109+
.alarm0 = S2MPG10_RTC_A0SEC,
110+
.alarm1 = S2MPG10_RTC_A1SEC,
111+
.udr_update = S2MPG10_RTC_UPDATE,
112+
.autoclear_udr_mask = S2MPS15_RTC_WUDR_MASK | S2MPS15_RTC_AUDR_MASK,
113+
.read_time_udr_mask = S2MPS_RTC_RUDR_MASK,
114+
.write_time_udr_mask = S2MPS15_RTC_WUDR_MASK,
115+
.write_alarm_udr_mask = S2MPS15_RTC_AUDR_MASK,
116+
};
117+
102118
/* Register map for S2MPS13 */
103119
static const struct s5m_rtc_reg_config s2mps13_rtc_regs = {
104120
.regs_count = 7,
@@ -238,6 +254,7 @@ static int s5m_check_peding_alarm_interrupt(struct s5m_rtc_info *info,
238254
ret = regmap_read(info->regmap, S5M_RTC_STATUS, &val);
239255
val &= S5M_ALARM0_STATUS;
240256
break;
257+
case S2MPG10:
241258
case S2MPS15X:
242259
case S2MPS14X:
243260
case S2MPS13X:
@@ -300,6 +317,7 @@ static int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info)
300317
case S5M8767X:
301318
data &= ~S5M_RTC_TIME_EN_MASK;
302319
break;
320+
case S2MPG10:
303321
case S2MPS15X:
304322
case S2MPS14X:
305323
case S2MPS13X:
@@ -351,6 +369,7 @@ static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm)
351369

352370
switch (info->device_type) {
353371
case S5M8767X:
372+
case S2MPG10:
354373
case S2MPS15X:
355374
case S2MPS14X:
356375
case S2MPS13X:
@@ -374,6 +393,7 @@ static int s5m_rtc_set_time(struct device *dev, struct rtc_time *tm)
374393

375394
switch (info->device_type) {
376395
case S5M8767X:
396+
case S2MPG10:
377397
case S2MPS15X:
378398
case S2MPS14X:
379399
case S2MPS13X:
@@ -411,6 +431,7 @@ static int s5m_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
411431

412432
switch (info->device_type) {
413433
case S5M8767X:
434+
case S2MPG10:
414435
case S2MPS15X:
415436
case S2MPS14X:
416437
case S2MPS13X:
@@ -449,6 +470,7 @@ static int s5m_rtc_stop_alarm(struct s5m_rtc_info *info)
449470

450471
switch (info->device_type) {
451472
case S5M8767X:
473+
case S2MPG10:
452474
case S2MPS15X:
453475
case S2MPS14X:
454476
case S2MPS13X:
@@ -487,6 +509,7 @@ static int s5m_rtc_start_alarm(struct s5m_rtc_info *info)
487509

488510
switch (info->device_type) {
489511
case S5M8767X:
512+
case S2MPG10:
490513
case S2MPS15X:
491514
case S2MPS14X:
492515
case S2MPS13X:
@@ -524,6 +547,7 @@ static int s5m_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
524547

525548
switch (info->device_type) {
526549
case S5M8767X:
550+
case S2MPG10:
527551
case S2MPS15X:
528552
case S2MPS14X:
529553
case S2MPS13X:
@@ -604,6 +628,7 @@ static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info)
604628
ret = regmap_raw_write(info->regmap, S5M_ALARM0_CONF, data, 2);
605629
break;
606630

631+
case S2MPG10:
607632
case S2MPS15X:
608633
case S2MPS14X:
609634
case S2MPS13X:
@@ -634,6 +659,25 @@ static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info)
634659
return ret;
635660
}
636661

662+
static int s5m_rtc_restart_s2mpg10(struct sys_off_data *data)
663+
{
664+
struct s5m_rtc_info *info = data->cb_data;
665+
int ret;
666+
667+
if (data->mode != REBOOT_COLD && data->mode != REBOOT_HARD)
668+
return NOTIFY_DONE;
669+
670+
/*
671+
* Arm watchdog with maximum timeout (2 seconds), and perform full reset
672+
* on expiry.
673+
*/
674+
ret = regmap_set_bits(info->regmap, S2MPG10_RTC_WTSR,
675+
(S2MPG10_WTSR_COLDTIMER | S2MPG10_WTSR_COLDRST
676+
| S2MPG10_WTSR_WTSRT | S2MPG10_WTSR_WTSR_EN));
677+
678+
return ret ? NOTIFY_BAD : NOTIFY_DONE;
679+
}
680+
637681
static int s5m_rtc_probe(struct platform_device *pdev)
638682
{
639683
struct sec_pmic_dev *s5m87xx = dev_get_drvdata(pdev->dev.parent);
@@ -689,6 +733,9 @@ static int s5m_rtc_probe(struct platform_device *pdev)
689733
if (IS_ERR(info->regmap))
690734
return dev_err_probe(&pdev->dev, PTR_ERR(info->regmap),
691735
"Failed to allocate regmap\n");
736+
} else if (device_type == S2MPG10) {
737+
info->regs = &s2mpg10_rtc_regs;
738+
alarm_irq = S2MPG10_IRQ_RTCA0;
692739
} else {
693740
return dev_err_probe(&pdev->dev, -ENODEV,
694741
"Unsupported device type %d\n",
@@ -735,6 +782,18 @@ static int s5m_rtc_probe(struct platform_device *pdev)
735782
device_init_wakeup(&pdev->dev, true);
736783
}
737784

785+
if (of_device_is_system_power_controller(pdev->dev.parent->of_node) &&
786+
info->device_type == S2MPG10) {
787+
ret = devm_register_sys_off_handler(&pdev->dev,
788+
SYS_OFF_MODE_RESTART,
789+
SYS_OFF_PRIO_HIGH + 1,
790+
s5m_rtc_restart_s2mpg10,
791+
info);
792+
if (ret)
793+
return dev_err_probe(&pdev->dev, ret,
794+
"Failed to register restart handler\n");
795+
}
796+
738797
return devm_rtc_register_device(info->rtc_dev);
739798
}
740799

@@ -766,6 +825,7 @@ static SIMPLE_DEV_PM_OPS(s5m_rtc_pm_ops, s5m_rtc_suspend, s5m_rtc_resume);
766825

767826
static const struct platform_device_id s5m_rtc_id[] = {
768827
{ "s5m-rtc", S5M8767X },
828+
{ "s2mpg10-rtc", S2MPG10 },
769829
{ "s2mps13-rtc", S2MPS13X },
770830
{ "s2mps14-rtc", S2MPS14X },
771831
{ "s2mps15-rtc", S2MPS15X },

0 commit comments

Comments
 (0)