mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-30 18:47:06 +00:00
190 lines
5.7 KiB
Diff
190 lines
5.7 KiB
Diff
|
From c15671ce05a038b8c92a6f1e24b0b850a154ba59 Mon Sep 17 00:00:00 2001
|
||
|
From: Valentin Caron <valentin.caron@foss.st.com>
|
||
|
Date: Mon, 22 Jul 2024 18:00:20 +0200
|
||
|
Subject: [PATCH] rtc: stm32: add pinctrl and pinmux interfaces
|
||
|
|
||
|
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 | 5 ++
|
||
|
drivers/rtc/rtc-stm32.c | 120 ++++++++++++++++++++++++++++++++++++++++
|
||
|
2 files changed, 125 insertions(+)
|
||
|
|
||
|
--- a/drivers/rtc/Kconfig
|
||
|
+++ b/drivers/rtc/Kconfig
|
||
|
@@ -1887,6 +1887,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.
|
||
|
--- a/drivers/rtc/rtc-stm32.c
|
||
|
+++ b/drivers/rtc/rtc-stm32.c
|
||
|
@@ -12,6 +12,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>
|
||
|
@@ -94,6 +97,14 @@
|
||
|
/* 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 {
|
||
|
@@ -149,6 +160,106 @@ static void stm32_rtc_wpr_lock(struct st
|
||
|
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;
|
||
|
@@ -723,6 +834,7 @@ static int stm32_rtc_probe(struct platfo
|
||
|
{
|
||
|
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);
|
||
|
@@ -834,6 +946,14 @@ static int stm32_rtc_probe(struct platfo
|
||
|
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
|