diff options
author | Alim Akhtar <alim.akhtar@samsung.com> | 2015-11-20 05:37:53 -0500 |
---|---|---|
committer | Lee Jones <lee.jones@linaro.org> | 2015-11-23 05:34:38 -0500 |
commit | a65e5efa7c5faa8c320fe56cc351d47fcd006749 (patch) | |
tree | 57acd43fae9eed4aba532efd44887bbb516d67f2 | |
parent | 51af20675800ffbd97bd48363a06e00f83de44c4 (diff) |
rtc: s5m.c: Add support for S2MPS15 RTC
RTC found in s2mps15 is almost same as one found on s2mps13
with few differences in RTC_UPDATE register fields, like:
1> Bit[4] and Bit[1] are reversed
- On s2mps13
WUDR -> bit[4], AUDR -> bit[1]
- On s2mps15
WUDR -> bit[1], AUDR -> bit[4]
2> In case of s2mps13, for alarm register, need to set both
WDUR and ADUR high, whereas for s2mps15 only set AUDR to high.
3> On s2mps15, WUDR, RUDR and AUDR functions should never be used
at the same time.
This patch add required changes to enable s2mps15 rtc timer.
Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com>
Reviewed-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Acked-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
-rw-r--r-- | drivers/rtc/rtc-s5m.c | 37 | ||||
-rw-r--r-- | include/linux/mfd/samsung/rtc.h | 2 |
2 files changed, 35 insertions, 4 deletions
diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c index f2504b4eef34..0d68a85dd429 100644 --- a/drivers/rtc/rtc-s5m.c +++ b/drivers/rtc/rtc-s5m.c | |||
@@ -188,6 +188,7 @@ static inline int s5m_check_peding_alarm_interrupt(struct s5m_rtc_info *info, | |||
188 | ret = regmap_read(info->regmap, S5M_RTC_STATUS, &val); | 188 | ret = regmap_read(info->regmap, S5M_RTC_STATUS, &val); |
189 | val &= S5M_ALARM0_STATUS; | 189 | val &= S5M_ALARM0_STATUS; |
190 | break; | 190 | break; |
191 | case S2MPS15X: | ||
191 | case S2MPS14X: | 192 | case S2MPS14X: |
192 | case S2MPS13X: | 193 | case S2MPS13X: |
193 | ret = regmap_read(info->s5m87xx->regmap_pmic, S2MPS14_REG_ST2, | 194 | ret = regmap_read(info->s5m87xx->regmap_pmic, S2MPS14_REG_ST2, |
@@ -219,9 +220,22 @@ static inline int s5m8767_rtc_set_time_reg(struct s5m_rtc_info *info) | |||
219 | return ret; | 220 | return ret; |
220 | } | 221 | } |
221 | 222 | ||
222 | data |= info->regs->rtc_udr_mask; | 223 | switch (info->device_type) { |
223 | if (info->device_type == S5M8763X || info->device_type == S5M8767X) | 224 | case S5M8763X: |
224 | data |= S5M_RTC_TIME_EN_MASK; | 225 | case S5M8767X: |
226 | data |= info->regs->rtc_udr_mask | S5M_RTC_TIME_EN_MASK; | ||
227 | case S2MPS15X: | ||
228 | /* As per UM, for write time register, set WUDR bit to high */ | ||
229 | data |= S2MPS15_RTC_WUDR_MASK; | ||
230 | break; | ||
231 | case S2MPS14X: | ||
232 | case S2MPS13X: | ||
233 | data |= info->regs->rtc_udr_mask; | ||
234 | break; | ||
235 | default: | ||
236 | return -EINVAL; | ||
237 | } | ||
238 | |||
225 | 239 | ||
226 | ret = regmap_write(info->regmap, info->regs->rtc_udr_update, data); | 240 | ret = regmap_write(info->regmap, info->regs->rtc_udr_update, data); |
227 | if (ret < 0) { | 241 | if (ret < 0) { |
@@ -252,6 +266,11 @@ static inline int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info) | |||
252 | case S5M8767X: | 266 | case S5M8767X: |
253 | data &= ~S5M_RTC_TIME_EN_MASK; | 267 | data &= ~S5M_RTC_TIME_EN_MASK; |
254 | break; | 268 | break; |
269 | case S2MPS15X: | ||
270 | /* As per UM, for write alarm, set A_UDR(bit[4]) to high | ||
271 | * rtc_udr_mask above sets bit[4] | ||
272 | */ | ||
273 | break; | ||
255 | case S2MPS14X: | 274 | case S2MPS14X: |
256 | data |= S2MPS_RTC_RUDR_MASK; | 275 | data |= S2MPS_RTC_RUDR_MASK; |
257 | break; | 276 | break; |
@@ -317,7 +336,8 @@ static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
317 | u8 data[info->regs->regs_count]; | 336 | u8 data[info->regs->regs_count]; |
318 | int ret; | 337 | int ret; |
319 | 338 | ||
320 | if (info->device_type == S2MPS14X || info->device_type == S2MPS13X) { | 339 | if (info->device_type == S2MPS15X || info->device_type == S2MPS14X || |
340 | info->device_type == S2MPS13X) { | ||
321 | ret = regmap_update_bits(info->regmap, | 341 | ret = regmap_update_bits(info->regmap, |
322 | info->regs->rtc_udr_update, | 342 | info->regs->rtc_udr_update, |
323 | S2MPS_RTC_RUDR_MASK, S2MPS_RTC_RUDR_MASK); | 343 | S2MPS_RTC_RUDR_MASK, S2MPS_RTC_RUDR_MASK); |
@@ -339,6 +359,7 @@ static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
339 | break; | 359 | break; |
340 | 360 | ||
341 | case S5M8767X: | 361 | case S5M8767X: |
362 | case S2MPS15X: | ||
342 | case S2MPS14X: | 363 | case S2MPS14X: |
343 | case S2MPS13X: | 364 | case S2MPS13X: |
344 | s5m8767_data_to_tm(data, tm, info->rtc_24hr_mode); | 365 | s5m8767_data_to_tm(data, tm, info->rtc_24hr_mode); |
@@ -366,6 +387,7 @@ static int s5m_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
366 | s5m8763_tm_to_data(tm, data); | 387 | s5m8763_tm_to_data(tm, data); |
367 | break; | 388 | break; |
368 | case S5M8767X: | 389 | case S5M8767X: |
390 | case S2MPS15X: | ||
369 | case S2MPS14X: | 391 | case S2MPS14X: |
370 | case S2MPS13X: | 392 | case S2MPS13X: |
371 | ret = s5m8767_tm_to_data(tm, data); | 393 | ret = s5m8767_tm_to_data(tm, data); |
@@ -414,6 +436,7 @@ static int s5m_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
414 | break; | 436 | break; |
415 | 437 | ||
416 | case S5M8767X: | 438 | case S5M8767X: |
439 | case S2MPS15X: | ||
417 | case S2MPS14X: | 440 | case S2MPS14X: |
418 | case S2MPS13X: | 441 | case S2MPS13X: |
419 | s5m8767_data_to_tm(data, &alrm->time, info->rtc_24hr_mode); | 442 | s5m8767_data_to_tm(data, &alrm->time, info->rtc_24hr_mode); |
@@ -463,6 +486,7 @@ static int s5m_rtc_stop_alarm(struct s5m_rtc_info *info) | |||
463 | break; | 486 | break; |
464 | 487 | ||
465 | case S5M8767X: | 488 | case S5M8767X: |
489 | case S2MPS15X: | ||
466 | case S2MPS14X: | 490 | case S2MPS14X: |
467 | case S2MPS13X: | 491 | case S2MPS13X: |
468 | for (i = 0; i < info->regs->regs_count; i++) | 492 | for (i = 0; i < info->regs->regs_count; i++) |
@@ -508,6 +532,7 @@ static int s5m_rtc_start_alarm(struct s5m_rtc_info *info) | |||
508 | break; | 532 | break; |
509 | 533 | ||
510 | case S5M8767X: | 534 | case S5M8767X: |
535 | case S2MPS15X: | ||
511 | case S2MPS14X: | 536 | case S2MPS14X: |
512 | case S2MPS13X: | 537 | case S2MPS13X: |
513 | data[RTC_SEC] |= ALARM_ENABLE_MASK; | 538 | data[RTC_SEC] |= ALARM_ENABLE_MASK; |
@@ -548,6 +573,7 @@ static int s5m_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
548 | break; | 573 | break; |
549 | 574 | ||
550 | case S5M8767X: | 575 | case S5M8767X: |
576 | case S2MPS15X: | ||
551 | case S2MPS14X: | 577 | case S2MPS14X: |
552 | case S2MPS13X: | 578 | case S2MPS13X: |
553 | s5m8767_tm_to_data(&alrm->time, data); | 579 | s5m8767_tm_to_data(&alrm->time, data); |
@@ -631,6 +657,7 @@ static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info) | |||
631 | ret = regmap_raw_write(info->regmap, S5M_ALARM0_CONF, data, 2); | 657 | ret = regmap_raw_write(info->regmap, S5M_ALARM0_CONF, data, 2); |
632 | break; | 658 | break; |
633 | 659 | ||
660 | case S2MPS15X: | ||
634 | case S2MPS14X: | 661 | case S2MPS14X: |
635 | case S2MPS13X: | 662 | case S2MPS13X: |
636 | data[0] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT); | 663 | data[0] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT); |
@@ -679,6 +706,7 @@ static int s5m_rtc_probe(struct platform_device *pdev) | |||
679 | return -ENOMEM; | 706 | return -ENOMEM; |
680 | 707 | ||
681 | switch (platform_get_device_id(pdev)->driver_data) { | 708 | switch (platform_get_device_id(pdev)->driver_data) { |
709 | case S2MPS15X: | ||
682 | case S2MPS14X: | 710 | case S2MPS14X: |
683 | case S2MPS13X: | 711 | case S2MPS13X: |
684 | regmap_cfg = &s2mps14_rtc_regmap_config; | 712 | regmap_cfg = &s2mps14_rtc_regmap_config; |
@@ -805,6 +833,7 @@ static const struct platform_device_id s5m_rtc_id[] = { | |||
805 | { "s5m-rtc", S5M8767X }, | 833 | { "s5m-rtc", S5M8767X }, |
806 | { "s2mps13-rtc", S2MPS13X }, | 834 | { "s2mps13-rtc", S2MPS13X }, |
807 | { "s2mps14-rtc", S2MPS14X }, | 835 | { "s2mps14-rtc", S2MPS14X }, |
836 | { "s2mps15-rtc", S2MPS15X }, | ||
808 | { }, | 837 | { }, |
809 | }; | 838 | }; |
810 | MODULE_DEVICE_TABLE(platform, s5m_rtc_id); | 839 | MODULE_DEVICE_TABLE(platform, s5m_rtc_id); |
diff --git a/include/linux/mfd/samsung/rtc.h b/include/linux/mfd/samsung/rtc.h index 29c30ac36020..a65e4655d470 100644 --- a/include/linux/mfd/samsung/rtc.h +++ b/include/linux/mfd/samsung/rtc.h | |||
@@ -107,6 +107,8 @@ enum s2mps_rtc_reg { | |||
107 | #define S2MPS_RTC_WUDR_MASK (1 << S2MPS_RTC_WUDR_SHIFT) | 107 | #define S2MPS_RTC_WUDR_MASK (1 << S2MPS_RTC_WUDR_SHIFT) |
108 | #define S2MPS13_RTC_AUDR_SHIFT 1 | 108 | #define S2MPS13_RTC_AUDR_SHIFT 1 |
109 | #define S2MPS13_RTC_AUDR_MASK (1 << S2MPS13_RTC_AUDR_SHIFT) | 109 | #define S2MPS13_RTC_AUDR_MASK (1 << S2MPS13_RTC_AUDR_SHIFT) |
110 | #define S2MPS15_RTC_WUDR_SHIFT 1 | ||
111 | #define S2MPS15_RTC_WUDR_MASK (1 << S2MPS15_RTC_WUDR_SHIFT) | ||
110 | #define S2MPS_RTC_RUDR_SHIFT 0 | 112 | #define S2MPS_RTC_RUDR_SHIFT 0 |
111 | #define S2MPS_RTC_RUDR_MASK (1 << S2MPS_RTC_RUDR_SHIFT) | 113 | #define S2MPS_RTC_RUDR_MASK (1 << S2MPS_RTC_RUDR_SHIFT) |
112 | #define RTC_TCON_SHIFT 1 | 114 | #define RTC_TCON_SHIFT 1 |