Commit 16ad2bc0 authored by Valentin Caron's avatar Valentin Caron Committed by Alexandre Belloni
Browse files

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: default avatarValentin Caron <valentin.caron@foss.st.com>
Reviewed-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Link: https://lore.kernel.org/r/20240722160022.454226-3-valentin.caron@foss.st.com


Signed-off-by: default avatarAlexandre Belloni <alexandre.belloni@bootlin.com>
parent 5b19519d
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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.
+120 −0
Original line number Diff line number Diff line
@@ -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>
@@ -107,6 +110,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 {
@@ -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