STM32 RTC can pulse some SOC pins when an RTC alarm expires. This patch adds this functionality for alarm A. The pulse can out on three pins RTC_OUT1, RTC_OUT2, RTC_OUT2_RMP (PC13, PB2, PI8 on stm32mp15) (PC13, PB2, PI1 on stm32mp13) (PC13, PF4/PF6, PI8 on stm32mp25). This patch only adds the functionality for devices which are using st,stm32mp1-rtc and st,stm32mp25-rtc compatible. Add "alarm-a" in pinmux functions. Signed-off-by: Valentin Caron <valentin.caron@xxxxxxxxxxx> --- drivers/rtc/rtc-stm32.c | 60 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c index a57d494b229c..802c1412e064 100644 --- a/drivers/rtc/rtc-stm32.c +++ b/drivers/rtc/rtc-stm32.c @@ -47,8 +47,10 @@ #define STM32_RTC_CR_ALRAE BIT(8) #define STM32_RTC_CR_ALRAIE BIT(12) #define STM32_RTC_CR_OSEL GENMASK(22, 21) +#define STM32_RTC_CR_OSEL_ALARM_A FIELD_PREP(STM32_RTC_CR_OSEL, 0x01) #define STM32_RTC_CR_COE BIT(23) #define STM32_RTC_CR_TAMPOE BIT(26) +#define STM32_RTC_CR_TAMPALRM_TYPE BIT(30) #define STM32_RTC_CR_OUT2EN BIT(31) /* STM32_RTC_ISR/STM32_RTC_ICSR bit fields */ @@ -158,6 +160,7 @@ struct stm32_rtc_data { bool need_accuracy; bool rif_protected; bool has_lsco; + bool has_alarm_out; }; struct stm32_rtc { @@ -245,6 +248,47 @@ struct stm32_rtc_pinmux_func { int (*action)(struct pinctrl_dev *pctl_dev, unsigned int pin); }; +static int stm32_rtc_pinmux_action_alarm(struct pinctrl_dev *pctldev, unsigned int pin) +{ + struct stm32_rtc *rtc = pinctrl_dev_get_drvdata(pctldev); + struct stm32_rtc_registers regs = rtc->data->regs; + unsigned int cr = readl_relaxed(rtc->base + regs.cr); + unsigned int cfgr = readl_relaxed(rtc->base + regs.cfgr); + + if (!rtc->data->has_alarm_out) + return -EPERM; + + cr &= ~STM32_RTC_CR_OSEL; + cr |= STM32_RTC_CR_OSEL_ALARM_A; + cr &= ~STM32_RTC_CR_TAMPOE; + cr &= ~STM32_RTC_CR_COE; + cr &= ~STM32_RTC_CR_TAMPALRM_TYPE; + + switch (pin) { + case OUT1: + cr &= ~STM32_RTC_CR_OUT2EN; + cfgr &= ~STM32_RTC_CFGR_OUT2_RMP; + break; + case OUT2: + cr |= STM32_RTC_CR_OUT2EN; + cfgr &= ~STM32_RTC_CFGR_OUT2_RMP; + break; + case OUT2_RMP: + cr |= STM32_RTC_CR_OUT2EN; + cfgr |= STM32_RTC_CFGR_OUT2_RMP; + break; + default: + return -EINVAL; + } + + stm32_rtc_wpr_unlock(rtc); + writel_relaxed(cr, rtc->base + regs.cr); + writel_relaxed(cfgr, rtc->base + regs.cfgr); + stm32_rtc_wpr_lock(rtc); + + return 0; +} + static int stm32_rtc_pinmux_lsco_available(struct pinctrl_dev *pctldev, unsigned int pin) { struct stm32_rtc *rtc = pinctrl_dev_get_drvdata(pctldev); @@ -307,6 +351,7 @@ static int stm32_rtc_pinmux_action_lsco(struct pinctrl_dev *pctldev, unsigned in static const struct stm32_rtc_pinmux_func stm32_rtc_pinmux_functions[] = { STM32_RTC_PINMUX("lsco", &stm32_rtc_pinmux_action_lsco, "out1", "out2_rmp"), + STM32_RTC_PINMUX("alarm-a", &stm32_rtc_pinmux_action_alarm, "out1", "out2", "out2_rmp"), }; static int stm32_rtc_pinmux_get_functions_count(struct pinctrl_dev *pctldev) @@ -763,6 +808,7 @@ static const struct stm32_rtc_data stm32_rtc_data = { .need_accuracy = false, .rif_protected = false, .has_lsco = false, + .has_alarm_out = false, .regs = { .tr = 0x00, .dr = 0x04, @@ -788,6 +834,7 @@ static const struct stm32_rtc_data stm32h7_rtc_data = { .need_accuracy = false, .rif_protected = false, .has_lsco = false, + .has_alarm_out = false, .regs = { .tr = 0x00, .dr = 0x04, @@ -822,6 +869,7 @@ static const struct stm32_rtc_data stm32mp1_data = { .need_accuracy = true, .rif_protected = false, .has_lsco = true, + .has_alarm_out = true, .regs = { .tr = 0x00, .dr = 0x04, @@ -847,6 +895,7 @@ static const struct stm32_rtc_data stm32mp25_data = { .need_accuracy = true, .rif_protected = true, .has_lsco = true, + .has_alarm_out = true, .regs = { .tr = 0x00, .dr = 0x04, @@ -878,6 +927,17 @@ MODULE_DEVICE_TABLE(of, stm32_rtc_of_match); static void stm32_rtc_clean_outs(struct stm32_rtc *rtc) { struct stm32_rtc_registers regs = rtc->data->regs; + unsigned int cr = readl_relaxed(rtc->base + regs.cr); + + cr &= ~STM32_RTC_CR_OSEL; + cr &= ~STM32_RTC_CR_TAMPOE; + cr &= ~STM32_RTC_CR_COE; + cr &= ~STM32_RTC_CR_TAMPALRM_TYPE; + cr &= ~STM32_RTC_CR_OUT2EN; + + stm32_rtc_wpr_unlock(rtc); + writel_relaxed(cr, rtc->base + regs.cr); + stm32_rtc_wpr_lock(rtc); if (regs.cfgr != UNDEF_REG) { unsigned int cfgr = readl_relaxed(rtc->base + regs.cfgr); -- 2.25.1