Commit 1c18b8ec authored by Antonio Borneo's avatar Antonio Borneo Committed by Alexandre Belloni

rtc: stm32: don't stop time counter if not needed

RTC counters are stopped when INIT bit in ISR register is set and
start counting from the (eventual) new value when INIT is reset.

In stm32_rtc_init(), called during probe, the INIT bit is set to
program the prescaler and the 24h mode. This halts the RTC counter
at each probe tentative causing the RTC time to loose from 0.3s to
0.8s at each kernel boot.
If the RTC is battery powered, both prescaler value and 24h mode
are kept during power cycle and there is no need to program them
again.

Check if the desired prescaler value and the 24h mode are already
programmed, then skip reprogramming them to avoid halting the time
counter.
Signed-off-by: default avatarAntonio Borneo <antonio.borneo@foss.st.com>
Signed-off-by: default avatarValentin Caron <valentin.caron@foss.st.com>
Link: https://lore.kernel.org/r/20230705174357.353616-3-valentin.caron@foss.st.comSigned-off-by: default avatarAlexandre Belloni <alexandre.belloni@bootlin.com>
parent f69cb2d6
...@@ -628,7 +628,7 @@ static int stm32_rtc_init(struct platform_device *pdev, ...@@ -628,7 +628,7 @@ static int stm32_rtc_init(struct platform_device *pdev,
const struct stm32_rtc_registers *regs = &rtc->data->regs; const struct stm32_rtc_registers *regs = &rtc->data->regs;
unsigned int prer, pred_a, pred_s, pred_a_max, pred_s_max, cr; unsigned int prer, pred_a, pred_s, pred_a_max, pred_s_max, cr;
unsigned int rate; unsigned int rate;
int ret = 0; int ret;
rate = clk_get_rate(rtc->rtc_ck); rate = clk_get_rate(rtc->rtc_ck);
...@@ -656,6 +656,20 @@ static int stm32_rtc_init(struct platform_device *pdev, ...@@ -656,6 +656,20 @@ static int stm32_rtc_init(struct platform_device *pdev,
"fast" : "slow"); "fast" : "slow");
} }
cr = readl_relaxed(rtc->base + regs->cr);
prer = readl_relaxed(rtc->base + regs->prer);
prer &= STM32_RTC_PRER_PRED_S | STM32_RTC_PRER_PRED_A;
pred_s = (pred_s << STM32_RTC_PRER_PRED_S_SHIFT) &
STM32_RTC_PRER_PRED_S;
pred_a = (pred_a << STM32_RTC_PRER_PRED_A_SHIFT) &
STM32_RTC_PRER_PRED_A;
/* quit if there is nothing to initialize */
if ((cr & STM32_RTC_CR_FMT) == 0 && prer == (pred_s | pred_a))
return 0;
stm32_rtc_wpr_unlock(rtc); stm32_rtc_wpr_unlock(rtc);
ret = stm32_rtc_enter_init_mode(rtc); ret = stm32_rtc_enter_init_mode(rtc);
...@@ -665,13 +679,10 @@ static int stm32_rtc_init(struct platform_device *pdev, ...@@ -665,13 +679,10 @@ static int stm32_rtc_init(struct platform_device *pdev,
goto end; goto end;
} }
prer = (pred_s << STM32_RTC_PRER_PRED_S_SHIFT) & STM32_RTC_PRER_PRED_S; writel_relaxed(pred_s, rtc->base + regs->prer);
writel_relaxed(prer, rtc->base + regs->prer); writel_relaxed(pred_a | pred_s, rtc->base + regs->prer);
prer |= (pred_a << STM32_RTC_PRER_PRED_A_SHIFT) & STM32_RTC_PRER_PRED_A;
writel_relaxed(prer, rtc->base + regs->prer);
/* Force 24h time format */ /* Force 24h time format */
cr = readl_relaxed(rtc->base + regs->cr);
cr &= ~STM32_RTC_CR_FMT; cr &= ~STM32_RTC_CR_FMT;
writel_relaxed(cr, rtc->base + regs->cr); writel_relaxed(cr, rtc->base + regs->cr);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment