]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
rtc: stm32: add pinctrl and pinmux interfaces
authorValentin Caron <valentin.caron@foss.st.com>
Mon, 22 Jul 2024 16:00:20 +0000 (18:00 +0200)
committerAlexandre Belloni <alexandre.belloni@bootlin.com>
Wed, 14 Aug 2024 09:37:07 +0000 (11:37 +0200)
STM32 RTC is capable to handle 3 specific pins of the soc.
"out1, out2 and out2_rmp". To handle this, we use pinctrl framework.
There is a single pin per group.

Signed-off-by: Valentin Caron <valentin.caron@foss.st.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Link: https://lore.kernel.org/r/20240722160022.454226-3-valentin.caron@foss.st.com
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
drivers/rtc/Kconfig
drivers/rtc/rtc-stm32.c

index 2a95b05982ad252f5e69a6bdbf49fe5c320a3a3e..4b1a87027a3d745c741ba008164c2cb801246d25 100644 (file)
@@ -1923,6 +1923,11 @@ config RTC_DRV_STM32
        tristate "STM32 RTC"
        select REGMAP_MMIO
        depends on ARCH_STM32 || COMPILE_TEST
+       depends on OF
+       depends on PINCTRL
+       select PINMUX
+       select PINCONF
+       select GENERIC_PINCONF
        help
           If you say yes here you get support for the STM32 On-Chip
           Real Time Clock.
index 98b07969609d29cbf25899c1f9d89022aba96afd..6dfd9dc07e2e6c67c5def4bfa14a5acf42ed847b 100644 (file)
@@ -13,6 +13,9 @@
 #include <linux/mfd/syscon.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinmux.h>
 #include <linux/platform_device.h>
 #include <linux/pm_wakeirq.h>
 #include <linux/regmap.h>
 /* STM32 RTC driver time helpers */
 #define SEC_PER_DAY            (24 * 60 * 60)
 
+/* STM32 RTC pinctrl helpers */
+#define STM32_RTC_PINMUX(_name, _action, ...) { \
+       .name = (_name), \
+       .action = (_action), \
+       .groups = ((const char *[]){ __VA_ARGS__ }), \
+       .num_groups = ARRAY_SIZE(((const char *[]){ __VA_ARGS__ })), \
+}
+
 struct stm32_rtc;
 
 struct stm32_rtc_registers {
@@ -171,6 +182,106 @@ static void stm32_rtc_wpr_lock(struct stm32_rtc *rtc)
        writel_relaxed(RTC_WPR_WRONG_KEY, rtc->base + regs->wpr);
 }
 
+enum stm32_rtc_pin_name {
+       NONE,
+       OUT1,
+       OUT2,
+       OUT2_RMP
+};
+
+static const struct pinctrl_pin_desc stm32_rtc_pinctrl_pins[] = {
+       PINCTRL_PIN(OUT1, "out1"),
+       PINCTRL_PIN(OUT2, "out2"),
+       PINCTRL_PIN(OUT2_RMP, "out2_rmp"),
+};
+
+static int stm32_rtc_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+       return ARRAY_SIZE(stm32_rtc_pinctrl_pins);
+}
+
+static const char *stm32_rtc_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+                                                   unsigned int selector)
+{
+       return stm32_rtc_pinctrl_pins[selector].name;
+}
+
+static int stm32_rtc_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+                                           unsigned int selector,
+                                           const unsigned int **pins,
+                                           unsigned int *num_pins)
+{
+       *pins = &stm32_rtc_pinctrl_pins[selector].number;
+       *num_pins = 1;
+       return 0;
+}
+
+static const struct pinctrl_ops stm32_rtc_pinctrl_ops = {
+       .dt_node_to_map         = pinconf_generic_dt_node_to_map_all,
+       .dt_free_map            = pinconf_generic_dt_free_map,
+       .get_groups_count       = stm32_rtc_pinctrl_get_groups_count,
+       .get_group_name         = stm32_rtc_pinctrl_get_group_name,
+       .get_group_pins         = stm32_rtc_pinctrl_get_group_pins,
+};
+
+struct stm32_rtc_pinmux_func {
+       const char *name;
+       const char * const *groups;
+       const unsigned int num_groups;
+       int (*action)(struct pinctrl_dev *pctl_dev, unsigned int pin);
+};
+
+static const struct stm32_rtc_pinmux_func stm32_rtc_pinmux_functions[] = {
+};
+
+static int stm32_rtc_pinmux_get_functions_count(struct pinctrl_dev *pctldev)
+{
+       return ARRAY_SIZE(stm32_rtc_pinmux_functions);
+}
+
+static const char *stm32_rtc_pinmux_get_fname(struct pinctrl_dev *pctldev, unsigned int selector)
+{
+       return stm32_rtc_pinmux_functions[selector].name;
+}
+
+static int stm32_rtc_pinmux_get_groups(struct pinctrl_dev *pctldev, unsigned int selector,
+                                      const char * const **groups, unsigned int * const num_groups)
+{
+       *groups = stm32_rtc_pinmux_functions[selector].groups;
+       *num_groups = stm32_rtc_pinmux_functions[selector].num_groups;
+       return 0;
+}
+
+static int stm32_rtc_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int selector,
+                                   unsigned int group)
+{
+       struct stm32_rtc_pinmux_func selected_func = stm32_rtc_pinmux_functions[selector];
+       struct pinctrl_pin_desc pin = stm32_rtc_pinctrl_pins[group];
+
+       /* Call action */
+       if (selected_func.action)
+               return selected_func.action(pctldev, pin.number);
+
+       return -EINVAL;
+}
+
+static const struct pinmux_ops stm32_rtc_pinmux_ops = {
+       .get_functions_count    = stm32_rtc_pinmux_get_functions_count,
+       .get_function_name      = stm32_rtc_pinmux_get_fname,
+       .get_function_groups    = stm32_rtc_pinmux_get_groups,
+       .set_mux                = stm32_rtc_pinmux_set_mux,
+       .strict                 = true,
+};
+
+static struct pinctrl_desc stm32_rtc_pdesc = {
+       .name = DRIVER_NAME,
+       .pins = stm32_rtc_pinctrl_pins,
+       .npins = ARRAY_SIZE(stm32_rtc_pinctrl_pins),
+       .owner = THIS_MODULE,
+       .pctlops = &stm32_rtc_pinctrl_ops,
+       .pmxops = &stm32_rtc_pinmux_ops,
+};
+
 static int stm32_rtc_enter_init_mode(struct stm32_rtc *rtc)
 {
        const struct stm32_rtc_registers *regs = &rtc->data->regs;
@@ -791,6 +902,7 @@ static int stm32_rtc_probe(struct platform_device *pdev)
 {
        struct stm32_rtc *rtc;
        const struct stm32_rtc_registers *regs;
+       struct pinctrl_dev *pctl;
        int ret;
 
        rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
@@ -912,6 +1024,14 @@ static int stm32_rtc_probe(struct platform_device *pdev)
                goto err;
        }
 
+       ret = devm_pinctrl_register_and_init(&pdev->dev, &stm32_rtc_pdesc, rtc, &pctl);
+       if (ret)
+               return dev_err_probe(&pdev->dev, ret, "pinctrl register failed");
+
+       ret = pinctrl_enable(pctl);
+       if (ret)
+               return dev_err_probe(&pdev->dev, ret, "pinctrl enable failed");
+
        /*
         * If INITS flag is reset (calendar year field set to 0x00), calendar
         * must be initialized