aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc/rtc-omap.c
diff options
context:
space:
mode:
authorMarcin Niestroj <m.niestroj@grinn-global.com>2016-09-16 05:26:28 -0400
committerAlexandre Belloni <alexandre.belloni@free-electrons.com>2016-09-21 15:46:04 -0400
commit97ea1906b3c2201273ea6bb40c43c611c056ddb3 (patch)
tree71548d748629fe2f6b63e2ea9b92b007a6bbdeb9 /drivers/rtc/rtc-omap.c
parent970fc7f4afd52d638d88aeda985ea03ccd33acee (diff)
rtc: omap: Support ext_wakeup configuration
Support configuration of ext_wakeup sources. This patch makes it possible to enable ext_wakeup and set it's polarity, depending on board configuration. AM335x's dedicated PMIC (tps65217) uses ext_wakeup to notify about power-button presses. Handling power-button presses enables to recover from RTC-only power states correctly. Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com> Acked-by: Tony Lindgren <tony@atomide.com> Acked-by: Rob Herring <robh@kernel.org> Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Diffstat (limited to 'drivers/rtc/rtc-omap.c')
-rw-r--r--drivers/rtc/rtc-omap.c168
1 files changed, 160 insertions, 8 deletions
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c
index cadac8e2aa6b..b04ea9b5ae67 100644
--- a/drivers/rtc/rtc-omap.c
+++ b/drivers/rtc/rtc-omap.c
@@ -13,19 +13,23 @@
13 * 2 of the License, or (at your option) any later version. 13 * 2 of the License, or (at your option) any later version.
14 */ 14 */
15 15
16#include <linux/kernel.h> 16#include <dt-bindings/gpio/gpio.h>
17#include <linux/bcd.h>
18#include <linux/clk.h>
19#include <linux/delay.h>
17#include <linux/init.h> 20#include <linux/init.h>
18#include <linux/module.h> 21#include <linux/io.h>
19#include <linux/ioport.h> 22#include <linux/ioport.h>
20#include <linux/delay.h> 23#include <linux/kernel.h>
21#include <linux/rtc.h> 24#include <linux/module.h>
22#include <linux/bcd.h>
23#include <linux/platform_device.h>
24#include <linux/of.h> 25#include <linux/of.h>
25#include <linux/of_device.h> 26#include <linux/of_device.h>
27#include <linux/pinctrl/pinctrl.h>
28#include <linux/pinctrl/pinconf.h>
29#include <linux/pinctrl/pinconf-generic.h>
30#include <linux/platform_device.h>
26#include <linux/pm_runtime.h> 31#include <linux/pm_runtime.h>
27#include <linux/io.h> 32#include <linux/rtc.h>
28#include <linux/clk.h>
29 33
30/* 34/*
31 * The OMAP RTC is a year/month/day/hours/minutes/seconds BCD clock 35 * The OMAP RTC is a year/month/day/hours/minutes/seconds BCD clock
@@ -115,6 +119,8 @@
115 119
116/* OMAP_RTC_PMIC bit fields: */ 120/* OMAP_RTC_PMIC bit fields: */
117#define OMAP_RTC_PMIC_POWER_EN_EN BIT(16) 121#define OMAP_RTC_PMIC_POWER_EN_EN BIT(16)
122#define OMAP_RTC_PMIC_EXT_WKUP_EN(x) BIT(x)
123#define OMAP_RTC_PMIC_EXT_WKUP_POL(x) BIT(4 + x)
118 124
119/* OMAP_RTC_KICKER values */ 125/* OMAP_RTC_KICKER values */
120#define KICK0_VALUE 0x83e70b13 126#define KICK0_VALUE 0x83e70b13
@@ -141,6 +147,7 @@ struct omap_rtc {
141 bool is_pmic_controller; 147 bool is_pmic_controller;
142 bool has_ext_clk; 148 bool has_ext_clk;
143 const struct omap_rtc_device_type *type; 149 const struct omap_rtc_device_type *type;
150 struct pinctrl_dev *pctldev;
144}; 151};
145 152
146static inline u8 rtc_read(struct omap_rtc *rtc, unsigned int reg) 153static inline u8 rtc_read(struct omap_rtc *rtc, unsigned int reg)
@@ -525,6 +532,139 @@ static const struct of_device_id omap_rtc_of_match[] = {
525}; 532};
526MODULE_DEVICE_TABLE(of, omap_rtc_of_match); 533MODULE_DEVICE_TABLE(of, omap_rtc_of_match);
527 534
535static const struct pinctrl_pin_desc rtc_pins_desc[] = {
536 PINCTRL_PIN(0, "ext_wakeup0"),
537 PINCTRL_PIN(1, "ext_wakeup1"),
538 PINCTRL_PIN(2, "ext_wakeup2"),
539 PINCTRL_PIN(3, "ext_wakeup3"),
540};
541
542static int rtc_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
543{
544 return 0;
545}
546
547static const char *rtc_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
548 unsigned int group)
549{
550 return NULL;
551}
552
553static const struct pinctrl_ops rtc_pinctrl_ops = {
554 .get_groups_count = rtc_pinctrl_get_groups_count,
555 .get_group_name = rtc_pinctrl_get_group_name,
556 .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
557 .dt_free_map = pinconf_generic_dt_free_map,
558};
559
560enum rtc_pin_config_param {
561 PIN_CONFIG_ACTIVE_HIGH = PIN_CONFIG_END + 1,
562};
563
564static const struct pinconf_generic_params rtc_params[] = {
565 {"ti,active-high", PIN_CONFIG_ACTIVE_HIGH, 0},
566};
567
568#ifdef CONFIG_DEBUG_FS
569static const struct pin_config_item rtc_conf_items[ARRAY_SIZE(rtc_params)] = {
570 PCONFDUMP(PIN_CONFIG_ACTIVE_HIGH, "input active high", NULL, false),
571};
572#endif
573
574static int rtc_pinconf_get(struct pinctrl_dev *pctldev,
575 unsigned int pin, unsigned long *config)
576{
577 struct omap_rtc *rtc = pinctrl_dev_get_drvdata(pctldev);
578 unsigned int param = pinconf_to_config_param(*config);
579 u32 val;
580 u16 arg = 0;
581
582 rtc->type->unlock(rtc);
583 val = rtc_readl(rtc, OMAP_RTC_PMIC_REG);
584 rtc->type->lock(rtc);
585
586 switch (param) {
587 case PIN_CONFIG_INPUT_ENABLE:
588 if (!(val & OMAP_RTC_PMIC_EXT_WKUP_EN(pin)))
589 return -EINVAL;
590 break;
591 case PIN_CONFIG_ACTIVE_HIGH:
592 if (val & OMAP_RTC_PMIC_EXT_WKUP_POL(pin))
593 return -EINVAL;
594 break;
595 default:
596 return -ENOTSUPP;
597 };
598
599 *config = pinconf_to_config_packed(param, arg);
600
601 return 0;
602}
603
604static int rtc_pinconf_set(struct pinctrl_dev *pctldev,
605 unsigned int pin, unsigned long *configs,
606 unsigned int num_configs)
607{
608 struct omap_rtc *rtc = pinctrl_dev_get_drvdata(pctldev);
609 u32 val;
610 unsigned int param;
611 u16 param_val;
612 int i;
613
614 rtc->type->unlock(rtc);
615 val = rtc_readl(rtc, OMAP_RTC_PMIC_REG);
616 rtc->type->lock(rtc);
617
618 /* active low by default */
619 val |= OMAP_RTC_PMIC_EXT_WKUP_POL(pin);
620
621 for (i = 0; i < num_configs; i++) {
622 param = pinconf_to_config_param(configs[i]);
623 param_val = pinconf_to_config_argument(configs[i]);
624
625 switch (param) {
626 case PIN_CONFIG_INPUT_ENABLE:
627 if (param_val)
628 val |= OMAP_RTC_PMIC_EXT_WKUP_EN(pin);
629 else
630 val &= ~OMAP_RTC_PMIC_EXT_WKUP_EN(pin);
631 break;
632 case PIN_CONFIG_ACTIVE_HIGH:
633 val &= ~OMAP_RTC_PMIC_EXT_WKUP_POL(pin);
634 break;
635 default:
636 dev_err(&rtc->rtc->dev, "Property %u not supported\n",
637 param);
638 return -ENOTSUPP;
639 }
640 }
641
642 rtc->type->unlock(rtc);
643 rtc_writel(rtc, OMAP_RTC_PMIC_REG, val);
644 rtc->type->lock(rtc);
645
646 return 0;
647}
648
649static const struct pinconf_ops rtc_pinconf_ops = {
650 .is_generic = true,
651 .pin_config_get = rtc_pinconf_get,
652 .pin_config_set = rtc_pinconf_set,
653};
654
655static struct pinctrl_desc rtc_pinctrl_desc = {
656 .pins = rtc_pins_desc,
657 .npins = ARRAY_SIZE(rtc_pins_desc),
658 .pctlops = &rtc_pinctrl_ops,
659 .confops = &rtc_pinconf_ops,
660 .custom_params = rtc_params,
661 .num_custom_params = ARRAY_SIZE(rtc_params),
662#ifdef CONFIG_DEBUG_FS
663 .custom_conf_items = rtc_conf_items,
664#endif
665 .owner = THIS_MODULE,
666};
667
528static int omap_rtc_probe(struct platform_device *pdev) 668static int omap_rtc_probe(struct platform_device *pdev)
529{ 669{
530 struct omap_rtc *rtc; 670 struct omap_rtc *rtc;
@@ -681,6 +821,15 @@ static int omap_rtc_probe(struct platform_device *pdev)
681 } 821 }
682 } 822 }
683 823
824 /* Support ext_wakeup pinconf */
825 rtc_pinctrl_desc.name = dev_name(&pdev->dev);
826
827 rtc->pctldev = pinctrl_register(&rtc_pinctrl_desc, &pdev->dev, rtc);
828 if (IS_ERR(rtc->pctldev)) {
829 dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
830 return PTR_ERR(rtc->pctldev);
831 }
832
684 return 0; 833 return 0;
685 834
686err: 835err:
@@ -724,6 +873,9 @@ static int __exit omap_rtc_remove(struct platform_device *pdev)
724 pm_runtime_put_sync(&pdev->dev); 873 pm_runtime_put_sync(&pdev->dev);
725 pm_runtime_disable(&pdev->dev); 874 pm_runtime_disable(&pdev->dev);
726 875
876 /* Remove ext_wakeup pinconf */
877 pinctrl_unregister(rtc->pctldev);
878
727 return 0; 879 return 0;
728} 880}
729 881