aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/rtc/Kconfig4
-rw-r--r--drivers/rtc/rtc-s5m.c101
2 files changed, 86 insertions, 19 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 71988b69eca6..0754f5c7cb3b 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -530,11 +530,11 @@ config RTC_DRV_RV3029C2
530 will be called rtc-rv3029c2. 530 will be called rtc-rv3029c2.
531 531
532config RTC_DRV_S5M 532config RTC_DRV_S5M
533 tristate "Samsung S5M series" 533 tristate "Samsung S2M/S5M series"
534 depends on MFD_SEC_CORE 534 depends on MFD_SEC_CORE
535 help 535 help
536 If you say yes here you will get support for the 536 If you say yes here you will get support for the
537 RTC of Samsung S5M PMIC series. 537 RTC of Samsung S2MPS14 and S5M PMIC series.
538 538
539 This driver can also be built as a module. If so, the module 539 This driver can also be built as a module. If so, the module
540 will be called rtc-s5m. 540 will be called rtc-s5m.
diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c
index 59860128a221..76287ebd0e35 100644
--- a/drivers/rtc/rtc-s5m.c
+++ b/drivers/rtc/rtc-s5m.c
@@ -17,16 +17,14 @@
17 17
18#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/i2c.h> 19#include <linux/i2c.h>
20#include <linux/slab.h>
21#include <linux/bcd.h> 20#include <linux/bcd.h>
22#include <linux/bitops.h>
23#include <linux/regmap.h> 21#include <linux/regmap.h>
24#include <linux/rtc.h> 22#include <linux/rtc.h>
25#include <linux/delay.h>
26#include <linux/platform_device.h> 23#include <linux/platform_device.h>
27#include <linux/mfd/samsung/core.h> 24#include <linux/mfd/samsung/core.h>
28#include <linux/mfd/samsung/irq.h> 25#include <linux/mfd/samsung/irq.h>
29#include <linux/mfd/samsung/rtc.h> 26#include <linux/mfd/samsung/rtc.h>
27#include <linux/mfd/samsung/s2mps14.h>
30 28
31/* 29/*
32 * Maximum number of retries for checking changes in UDR field 30 * Maximum number of retries for checking changes in UDR field
@@ -74,6 +72,21 @@ static const struct s5m_rtc_reg_config s5m_rtc_regs = {
74 .rtc_udr_mask = S5M_RTC_UDR_MASK, 72 .rtc_udr_mask = S5M_RTC_UDR_MASK,
75}; 73};
76 74
75/*
76 * Register map for S2MPS14.
77 * It may be also suitable for S2MPS11 but this was not tested.
78 */
79static const struct s5m_rtc_reg_config s2mps_rtc_regs = {
80 .regs_count = 7,
81 .time = S2MPS_RTC_SEC,
82 .ctrl = S2MPS_RTC_CTRL,
83 .alarm0 = S2MPS_ALARM0_SEC,
84 .alarm1 = S2MPS_ALARM1_SEC,
85 .smpl_wtsr = S2MPS_WTSR_SMPL_CNTL,
86 .rtc_udr_update = S2MPS_RTC_UDR_CON,
87 .rtc_udr_mask = S2MPS_RTC_WUDR_MASK,
88};
89
77struct s5m_rtc_info { 90struct s5m_rtc_info {
78 struct device *dev; 91 struct device *dev;
79 struct i2c_client *i2c; 92 struct i2c_client *i2c;
@@ -178,6 +191,11 @@ static inline int s5m_check_peding_alarm_interrupt(struct s5m_rtc_info *info,
178 ret = regmap_read(info->regmap, S5M_RTC_STATUS, &val); 191 ret = regmap_read(info->regmap, S5M_RTC_STATUS, &val);
179 val &= S5M_ALARM0_STATUS; 192 val &= S5M_ALARM0_STATUS;
180 break; 193 break;
194 case S2MPS14X:
195 ret = regmap_read(info->s5m87xx->regmap_pmic, S2MPS14_REG_ST2,
196 &val);
197 val &= S2MPS_ALARM0_STATUS;
198 break;
181 default: 199 default:
182 return -EINVAL; 200 return -EINVAL;
183 } 201 }
@@ -203,8 +221,9 @@ static inline int s5m8767_rtc_set_time_reg(struct s5m_rtc_info *info)
203 return ret; 221 return ret;
204 } 222 }
205 223
206 data |= S5M_RTC_TIME_EN_MASK;
207 data |= info->regs->rtc_udr_mask; 224 data |= info->regs->rtc_udr_mask;
225 if (info->device_type == S5M8763X || info->device_type == S5M8767X)
226 data |= S5M_RTC_TIME_EN_MASK;
208 227
209 ret = regmap_write(info->regmap, info->regs->rtc_udr_update, data); 228 ret = regmap_write(info->regmap, info->regs->rtc_udr_update, data);
210 if (ret < 0) { 229 if (ret < 0) {
@@ -229,8 +248,18 @@ static inline int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info)
229 return ret; 248 return ret;
230 } 249 }
231 250
232 data &= ~S5M_RTC_TIME_EN_MASK;
233 data |= info->regs->rtc_udr_mask; 251 data |= info->regs->rtc_udr_mask;
252 switch (info->device_type) {
253 case S5M8763X:
254 case S5M8767X:
255 data &= ~S5M_RTC_TIME_EN_MASK;
256 break;
257 case S2MPS14X:
258 data |= S2MPS_RTC_RUDR_MASK;
259 break;
260 default:
261 return -EINVAL;
262 }
234 263
235 ret = regmap_write(info->regmap, info->regs->rtc_udr_update, data); 264 ret = regmap_write(info->regmap, info->regs->rtc_udr_update, data);
236 if (ret < 0) { 265 if (ret < 0) {
@@ -282,6 +311,17 @@ static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm)
282 u8 data[info->regs->regs_count]; 311 u8 data[info->regs->regs_count];
283 int ret; 312 int ret;
284 313
314 if (info->device_type == S2MPS14X) {
315 ret = regmap_update_bits(info->regmap,
316 info->regs->rtc_udr_update,
317 S2MPS_RTC_RUDR_MASK, S2MPS_RTC_RUDR_MASK);
318 if (ret) {
319 dev_err(dev,
320 "Failed to prepare registers for time reading: %d\n",
321 ret);
322 return ret;
323 }
324 }
285 ret = regmap_bulk_read(info->regmap, info->regs->time, data, 325 ret = regmap_bulk_read(info->regmap, info->regs->time, data,
286 info->regs->regs_count); 326 info->regs->regs_count);
287 if (ret < 0) 327 if (ret < 0)
@@ -293,6 +333,7 @@ static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm)
293 break; 333 break;
294 334
295 case S5M8767X: 335 case S5M8767X:
336 case S2MPS14X:
296 s5m8767_data_to_tm(data, tm, info->rtc_24hr_mode); 337 s5m8767_data_to_tm(data, tm, info->rtc_24hr_mode);
297 break; 338 break;
298 339
@@ -318,6 +359,7 @@ static int s5m_rtc_set_time(struct device *dev, struct rtc_time *tm)
318 s5m8763_tm_to_data(tm, data); 359 s5m8763_tm_to_data(tm, data);
319 break; 360 break;
320 case S5M8767X: 361 case S5M8767X:
362 case S2MPS14X:
321 ret = s5m8767_tm_to_data(tm, data); 363 ret = s5m8767_tm_to_data(tm, data);
322 break; 364 break;
323 default: 365 default:
@@ -364,6 +406,7 @@ static int s5m_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
364 break; 406 break;
365 407
366 case S5M8767X: 408 case S5M8767X:
409 case S2MPS14X:
367 s5m8767_data_to_tm(data, &alrm->time, info->rtc_24hr_mode); 410 s5m8767_data_to_tm(data, &alrm->time, info->rtc_24hr_mode);
368 alrm->enabled = 0; 411 alrm->enabled = 0;
369 for (i = 0; i < info->regs->regs_count; i++) { 412 for (i = 0; i < info->regs->regs_count; i++) {
@@ -411,6 +454,7 @@ static int s5m_rtc_stop_alarm(struct s5m_rtc_info *info)
411 break; 454 break;
412 455
413 case S5M8767X: 456 case S5M8767X:
457 case S2MPS14X:
414 for (i = 0; i < info->regs->regs_count; i++) 458 for (i = 0; i < info->regs->regs_count; i++)
415 data[i] &= ~ALARM_ENABLE_MASK; 459 data[i] &= ~ALARM_ENABLE_MASK;
416 460
@@ -454,6 +498,7 @@ static int s5m_rtc_start_alarm(struct s5m_rtc_info *info)
454 break; 498 break;
455 499
456 case S5M8767X: 500 case S5M8767X:
501 case S2MPS14X:
457 data[RTC_SEC] |= ALARM_ENABLE_MASK; 502 data[RTC_SEC] |= ALARM_ENABLE_MASK;
458 data[RTC_MIN] |= ALARM_ENABLE_MASK; 503 data[RTC_MIN] |= ALARM_ENABLE_MASK;
459 data[RTC_HOUR] |= ALARM_ENABLE_MASK; 504 data[RTC_HOUR] |= ALARM_ENABLE_MASK;
@@ -492,6 +537,7 @@ static int s5m_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
492 break; 537 break;
493 538
494 case S5M8767X: 539 case S5M8767X:
540 case S2MPS14X:
495 s5m8767_tm_to_data(&alrm->time, data); 541 s5m8767_tm_to_data(&alrm->time, data);
496 break; 542 break;
497 543
@@ -578,19 +624,33 @@ static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info)
578 u8 data[2]; 624 u8 data[2];
579 int ret; 625 int ret;
580 626
581 /* UDR update time. Default of 7.32 ms is too long. */ 627 switch (info->device_type) {
582 ret = regmap_update_bits(info->regmap, S5M_RTC_UDR_CON, 628 case S5M8763X:
583 S5M_RTC_UDR_T_MASK, S5M_RTC_UDR_T_450_US); 629 case S5M8767X:
584 if (ret < 0) 630 /* UDR update time. Default of 7.32 ms is too long. */
585 dev_err(info->dev, "%s: fail to change UDR time: %d\n", 631 ret = regmap_update_bits(info->regmap, S5M_RTC_UDR_CON,
586 __func__, ret); 632 S5M_RTC_UDR_T_MASK, S5M_RTC_UDR_T_450_US);
633 if (ret < 0)
634 dev_err(info->dev, "%s: fail to change UDR time: %d\n",
635 __func__, ret);
587 636
588 /* Set RTC control register : Binary mode, 24hour mode */ 637 /* Set RTC control register : Binary mode, 24hour mode */
589 data[0] = (1 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT); 638 data[0] = (1 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT);
590 data[1] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT); 639 data[1] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT);
640
641 ret = regmap_raw_write(info->regmap, S5M_ALARM0_CONF, data, 2);
642 break;
643
644 case S2MPS14X:
645 data[0] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT);
646 ret = regmap_write(info->regmap, info->regs->ctrl, data[0]);
647 break;
648
649 default:
650 return -EINVAL;
651 }
591 652
592 info->rtc_24hr_mode = 1; 653 info->rtc_24hr_mode = 1;
593 ret = regmap_raw_write(info->regmap, S5M_ALARM0_CONF, data, 2);
594 if (ret < 0) { 654 if (ret < 0) {
595 dev_err(info->dev, "%s: fail to write controlm reg(%d)\n", 655 dev_err(info->dev, "%s: fail to write controlm reg(%d)\n",
596 __func__, ret); 656 __func__, ret);
@@ -620,6 +680,7 @@ static int s5m_rtc_probe(struct platform_device *pdev)
620 switch (pdata->device_type) { 680 switch (pdata->device_type) {
621 case S2MPS14X: 681 case S2MPS14X:
622 regmap_cfg = &s2mps14_rtc_regmap_config; 682 regmap_cfg = &s2mps14_rtc_regmap_config;
683 info->regs = &s2mps_rtc_regs;
623 break; 684 break;
624 case S5M8763X: 685 case S5M8763X:
625 regmap_cfg = &s5m_rtc_regmap_config; 686 regmap_cfg = &s5m_rtc_regmap_config;
@@ -654,6 +715,11 @@ static int s5m_rtc_probe(struct platform_device *pdev)
654 info->wtsr_smpl = s5m87xx->wtsr_smpl; 715 info->wtsr_smpl = s5m87xx->wtsr_smpl;
655 716
656 switch (pdata->device_type) { 717 switch (pdata->device_type) {
718 case S2MPS14X:
719 info->irq = regmap_irq_get_virq(s5m87xx->irq_data,
720 S2MPS14_IRQ_RTCA0);
721 break;
722
657 case S5M8763X: 723 case S5M8763X:
658 info->irq = regmap_irq_get_virq(s5m87xx->irq_data, 724 info->irq = regmap_irq_get_virq(s5m87xx->irq_data,
659 S5M8763_IRQ_ALARM0); 725 S5M8763_IRQ_ALARM0);
@@ -768,7 +834,8 @@ static int s5m_rtc_suspend(struct device *dev)
768static SIMPLE_DEV_PM_OPS(s5m_rtc_pm_ops, s5m_rtc_suspend, s5m_rtc_resume); 834static SIMPLE_DEV_PM_OPS(s5m_rtc_pm_ops, s5m_rtc_suspend, s5m_rtc_resume);
769 835
770static const struct platform_device_id s5m_rtc_id[] = { 836static const struct platform_device_id s5m_rtc_id[] = {
771 { "s5m-rtc", 0 }, 837 { "s5m-rtc", S5M8767X },
838 { "s2mps14-rtc", S2MPS14X },
772}; 839};
773 840
774static struct platform_driver s5m_rtc_driver = { 841static struct platform_driver s5m_rtc_driver = {
@@ -787,6 +854,6 @@ module_platform_driver(s5m_rtc_driver);
787 854
788/* Module information */ 855/* Module information */
789MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>"); 856MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
790MODULE_DESCRIPTION("Samsung S5M RTC driver"); 857MODULE_DESCRIPTION("Samsung S5M/S2MPS14 RTC driver");
791MODULE_LICENSE("GPL"); 858MODULE_LICENSE("GPL");
792MODULE_ALIAS("platform:s5m-rtc"); 859MODULE_ALIAS("platform:s5m-rtc");