diff options
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/rtc-s5m.c | 75 |
1 files changed, 70 insertions, 5 deletions
diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c index 476af93543f6..8ec2d6a1dbe1 100644 --- a/drivers/rtc/rtc-s5m.c +++ b/drivers/rtc/rtc-s5m.c | |||
@@ -40,6 +40,7 @@ | |||
40 | 40 | ||
41 | struct s5m_rtc_info { | 41 | struct s5m_rtc_info { |
42 | struct device *dev; | 42 | struct device *dev; |
43 | struct i2c_client *i2c; | ||
43 | struct sec_pmic_dev *s5m87xx; | 44 | struct sec_pmic_dev *s5m87xx; |
44 | struct regmap *regmap; | 45 | struct regmap *regmap; |
45 | struct rtc_device *rtc_dev; | 46 | struct rtc_device *rtc_dev; |
@@ -49,6 +50,20 @@ struct s5m_rtc_info { | |||
49 | bool wtsr_smpl; | 50 | bool wtsr_smpl; |
50 | }; | 51 | }; |
51 | 52 | ||
53 | static const struct regmap_config s5m_rtc_regmap_config = { | ||
54 | .reg_bits = 8, | ||
55 | .val_bits = 8, | ||
56 | |||
57 | .max_register = SEC_RTC_REG_MAX, | ||
58 | }; | ||
59 | |||
60 | static const struct regmap_config s2mps14_rtc_regmap_config = { | ||
61 | .reg_bits = 8, | ||
62 | .val_bits = 8, | ||
63 | |||
64 | .max_register = S2MPS_RTC_REG_MAX, | ||
65 | }; | ||
66 | |||
52 | static void s5m8767_data_to_tm(u8 *data, struct rtc_time *tm, | 67 | static void s5m8767_data_to_tm(u8 *data, struct rtc_time *tm, |
53 | int rtc_24hr_mode) | 68 | int rtc_24hr_mode) |
54 | { | 69 | { |
@@ -554,6 +569,7 @@ static int s5m_rtc_probe(struct platform_device *pdev) | |||
554 | struct sec_pmic_dev *s5m87xx = dev_get_drvdata(pdev->dev.parent); | 569 | struct sec_pmic_dev *s5m87xx = dev_get_drvdata(pdev->dev.parent); |
555 | struct sec_platform_data *pdata = s5m87xx->pdata; | 570 | struct sec_platform_data *pdata = s5m87xx->pdata; |
556 | struct s5m_rtc_info *info; | 571 | struct s5m_rtc_info *info; |
572 | const struct regmap_config *regmap_cfg; | ||
557 | int ret; | 573 | int ret; |
558 | 574 | ||
559 | if (!pdata) { | 575 | if (!pdata) { |
@@ -565,9 +581,37 @@ static int s5m_rtc_probe(struct platform_device *pdev) | |||
565 | if (!info) | 581 | if (!info) |
566 | return -ENOMEM; | 582 | return -ENOMEM; |
567 | 583 | ||
584 | switch (pdata->device_type) { | ||
585 | case S2MPS14X: | ||
586 | regmap_cfg = &s2mps14_rtc_regmap_config; | ||
587 | break; | ||
588 | case S5M8763X: | ||
589 | regmap_cfg = &s5m_rtc_regmap_config; | ||
590 | break; | ||
591 | case S5M8767X: | ||
592 | regmap_cfg = &s5m_rtc_regmap_config; | ||
593 | break; | ||
594 | default: | ||
595 | dev_err(&pdev->dev, "Device type is not supported by RTC driver\n"); | ||
596 | return -ENODEV; | ||
597 | } | ||
598 | |||
599 | info->i2c = i2c_new_dummy(s5m87xx->i2c->adapter, RTC_I2C_ADDR); | ||
600 | if (!info->i2c) { | ||
601 | dev_err(&pdev->dev, "Failed to allocate I2C for RTC\n"); | ||
602 | return -ENODEV; | ||
603 | } | ||
604 | |||
605 | info->regmap = devm_regmap_init_i2c(info->i2c, regmap_cfg); | ||
606 | if (IS_ERR(info->regmap)) { | ||
607 | ret = PTR_ERR(info->regmap); | ||
608 | dev_err(&pdev->dev, "Failed to allocate RTC register map: %d\n", | ||
609 | ret); | ||
610 | goto err; | ||
611 | } | ||
612 | |||
568 | info->dev = &pdev->dev; | 613 | info->dev = &pdev->dev; |
569 | info->s5m87xx = s5m87xx; | 614 | info->s5m87xx = s5m87xx; |
570 | info->regmap = s5m87xx->regmap_rtc; | ||
571 | info->device_type = s5m87xx->device_type; | 615 | info->device_type = s5m87xx->device_type; |
572 | info->wtsr_smpl = s5m87xx->wtsr_smpl; | 616 | info->wtsr_smpl = s5m87xx->wtsr_smpl; |
573 | 617 | ||
@@ -585,7 +629,7 @@ static int s5m_rtc_probe(struct platform_device *pdev) | |||
585 | default: | 629 | default: |
586 | ret = -EINVAL; | 630 | ret = -EINVAL; |
587 | dev_err(&pdev->dev, "Unsupported device type: %d\n", ret); | 631 | dev_err(&pdev->dev, "Unsupported device type: %d\n", ret); |
588 | return ret; | 632 | goto err; |
589 | } | 633 | } |
590 | 634 | ||
591 | platform_set_drvdata(pdev, info); | 635 | platform_set_drvdata(pdev, info); |
@@ -602,15 +646,24 @@ static int s5m_rtc_probe(struct platform_device *pdev) | |||
602 | info->rtc_dev = devm_rtc_device_register(&pdev->dev, "s5m-rtc", | 646 | info->rtc_dev = devm_rtc_device_register(&pdev->dev, "s5m-rtc", |
603 | &s5m_rtc_ops, THIS_MODULE); | 647 | &s5m_rtc_ops, THIS_MODULE); |
604 | 648 | ||
605 | if (IS_ERR(info->rtc_dev)) | 649 | if (IS_ERR(info->rtc_dev)) { |
606 | return PTR_ERR(info->rtc_dev); | 650 | ret = PTR_ERR(info->rtc_dev); |
651 | goto err; | ||
652 | } | ||
607 | 653 | ||
608 | ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL, | 654 | ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL, |
609 | s5m_rtc_alarm_irq, 0, "rtc-alarm0", | 655 | s5m_rtc_alarm_irq, 0, "rtc-alarm0", |
610 | info); | 656 | info); |
611 | if (ret < 0) | 657 | if (ret < 0) { |
612 | dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", | 658 | dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", |
613 | info->irq, ret); | 659 | info->irq, ret); |
660 | goto err; | ||
661 | } | ||
662 | |||
663 | return 0; | ||
664 | |||
665 | err: | ||
666 | i2c_unregister_device(info->i2c); | ||
614 | 667 | ||
615 | return ret; | 668 | return ret; |
616 | } | 669 | } |
@@ -639,6 +692,17 @@ static void s5m_rtc_shutdown(struct platform_device *pdev) | |||
639 | s5m_rtc_enable_smpl(info, false); | 692 | s5m_rtc_enable_smpl(info, false); |
640 | } | 693 | } |
641 | 694 | ||
695 | static int s5m_rtc_remove(struct platform_device *pdev) | ||
696 | { | ||
697 | struct s5m_rtc_info *info = platform_get_drvdata(pdev); | ||
698 | |||
699 | /* Perform also all shutdown steps when removing */ | ||
700 | s5m_rtc_shutdown(pdev); | ||
701 | i2c_unregister_device(info->i2c); | ||
702 | |||
703 | return 0; | ||
704 | } | ||
705 | |||
642 | #ifdef CONFIG_PM_SLEEP | 706 | #ifdef CONFIG_PM_SLEEP |
643 | static int s5m_rtc_resume(struct device *dev) | 707 | static int s5m_rtc_resume(struct device *dev) |
644 | { | 708 | { |
@@ -676,6 +740,7 @@ static struct platform_driver s5m_rtc_driver = { | |||
676 | .pm = &s5m_rtc_pm_ops, | 740 | .pm = &s5m_rtc_pm_ops, |
677 | }, | 741 | }, |
678 | .probe = s5m_rtc_probe, | 742 | .probe = s5m_rtc_probe, |
743 | .remove = s5m_rtc_remove, | ||
679 | .shutdown = s5m_rtc_shutdown, | 744 | .shutdown = s5m_rtc_shutdown, |
680 | .id_table = s5m_rtc_id, | 745 | .id_table = s5m_rtc_id, |
681 | }; | 746 | }; |