rtc: stm32: add alarm A out feature
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@foss.st.com> Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Link: https://lore.kernel.org/r/20240722160022.454226-5-valentin.caron@foss.st.com Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
This commit is contained in:
parent
bb7b0df2be
commit
04dcadb87d
1 changed files with 60 additions and 0 deletions
|
@ -47,8 +47,10 @@
|
||||||
#define STM32_RTC_CR_ALRAE BIT(8)
|
#define STM32_RTC_CR_ALRAE BIT(8)
|
||||||
#define STM32_RTC_CR_ALRAIE BIT(12)
|
#define STM32_RTC_CR_ALRAIE BIT(12)
|
||||||
#define STM32_RTC_CR_OSEL GENMASK(22, 21)
|
#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_COE BIT(23)
|
||||||
#define STM32_RTC_CR_TAMPOE BIT(26)
|
#define STM32_RTC_CR_TAMPOE BIT(26)
|
||||||
|
#define STM32_RTC_CR_TAMPALRM_TYPE BIT(30)
|
||||||
#define STM32_RTC_CR_OUT2EN BIT(31)
|
#define STM32_RTC_CR_OUT2EN BIT(31)
|
||||||
|
|
||||||
/* STM32_RTC_ISR/STM32_RTC_ICSR bit fields */
|
/* STM32_RTC_ISR/STM32_RTC_ICSR bit fields */
|
||||||
|
@ -158,6 +160,7 @@ struct stm32_rtc_data {
|
||||||
bool need_accuracy;
|
bool need_accuracy;
|
||||||
bool rif_protected;
|
bool rif_protected;
|
||||||
bool has_lsco;
|
bool has_lsco;
|
||||||
|
bool has_alarm_out;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct stm32_rtc {
|
struct stm32_rtc {
|
||||||
|
@ -245,6 +248,47 @@ struct stm32_rtc_pinmux_func {
|
||||||
int (*action)(struct pinctrl_dev *pctl_dev, unsigned int pin);
|
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)
|
static int stm32_rtc_pinmux_lsco_available(struct pinctrl_dev *pctldev, unsigned int pin)
|
||||||
{
|
{
|
||||||
struct stm32_rtc *rtc = pinctrl_dev_get_drvdata(pctldev);
|
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[] = {
|
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("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)
|
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,
|
.need_accuracy = false,
|
||||||
.rif_protected = false,
|
.rif_protected = false,
|
||||||
.has_lsco = false,
|
.has_lsco = false,
|
||||||
|
.has_alarm_out = false,
|
||||||
.regs = {
|
.regs = {
|
||||||
.tr = 0x00,
|
.tr = 0x00,
|
||||||
.dr = 0x04,
|
.dr = 0x04,
|
||||||
|
@ -788,6 +834,7 @@ static const struct stm32_rtc_data stm32h7_rtc_data = {
|
||||||
.need_accuracy = false,
|
.need_accuracy = false,
|
||||||
.rif_protected = false,
|
.rif_protected = false,
|
||||||
.has_lsco = false,
|
.has_lsco = false,
|
||||||
|
.has_alarm_out = false,
|
||||||
.regs = {
|
.regs = {
|
||||||
.tr = 0x00,
|
.tr = 0x00,
|
||||||
.dr = 0x04,
|
.dr = 0x04,
|
||||||
|
@ -822,6 +869,7 @@ static const struct stm32_rtc_data stm32mp1_data = {
|
||||||
.need_accuracy = true,
|
.need_accuracy = true,
|
||||||
.rif_protected = false,
|
.rif_protected = false,
|
||||||
.has_lsco = true,
|
.has_lsco = true,
|
||||||
|
.has_alarm_out = true,
|
||||||
.regs = {
|
.regs = {
|
||||||
.tr = 0x00,
|
.tr = 0x00,
|
||||||
.dr = 0x04,
|
.dr = 0x04,
|
||||||
|
@ -847,6 +895,7 @@ static const struct stm32_rtc_data stm32mp25_data = {
|
||||||
.need_accuracy = true,
|
.need_accuracy = true,
|
||||||
.rif_protected = true,
|
.rif_protected = true,
|
||||||
.has_lsco = true,
|
.has_lsco = true,
|
||||||
|
.has_alarm_out = true,
|
||||||
.regs = {
|
.regs = {
|
||||||
.tr = 0x00,
|
.tr = 0x00,
|
||||||
.dr = 0x04,
|
.dr = 0x04,
|
||||||
|
@ -878,6 +927,17 @@ MODULE_DEVICE_TABLE(of, stm32_rtc_of_match);
|
||||||
static void stm32_rtc_clean_outs(struct stm32_rtc *rtc)
|
static void stm32_rtc_clean_outs(struct stm32_rtc *rtc)
|
||||||
{
|
{
|
||||||
struct stm32_rtc_registers regs = rtc->data->regs;
|
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) {
|
if (regs.cfgr != UNDEF_REG) {
|
||||||
unsigned int cfgr = readl_relaxed(rtc->base + regs.cfgr);
|
unsigned int cfgr = readl_relaxed(rtc->base + regs.cfgr);
|
||||||
|
|
Loading…
Add table
Reference in a new issue