[PATCH 3/7] rtc: stm32: improve rtc precision

Alexandre Belloni alexandre.belloni at bootlin.com
Sun Jun 25 16:14:54 PDT 2023


On 15/06/2023 11:27:49+0200, Valentin Caron wrote:
> From: Christophe Guibout <christophe.guibout at foss.st.com>
> 
> The rtc is used to update the stgen counter on wake up from
> low power modes, so it needs to be as much accurate as possible.
> 
> The maximization of asynchronous divider leads to a 4ms rtc
> precision clock.
> By decreasing pred_a to 0, it will have pred_s=32767 (when
> need_accuracy is true), so stgen clock becomes more accurate
> with 30us precision.
> Nevertheless this will leads to an increase of power consumption.
> 
> Signed-off-by: Christophe Guibout <christophe.guibout at foss.st.com>
> Signed-off-by: Valentin Caron <valentin.caron at foss.st.com>
> ---
>  drivers/rtc/rtc-stm32.c | 26 ++++++++++++++++++++++----
>  1 file changed, 22 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c
> index bd7a59a07537..cad88668bcfb 100644
> --- a/drivers/rtc/rtc-stm32.c
> +++ b/drivers/rtc/rtc-stm32.c
> @@ -114,6 +114,7 @@ struct stm32_rtc_data {
>  	void (*clear_events)(struct stm32_rtc *rtc, unsigned int flags);
>  	bool has_pclk;
>  	bool need_dbp;
> +	bool need_accuracy;
>  };
>  
>  struct stm32_rtc {
> @@ -545,6 +546,7 @@ static void stm32_rtc_clear_events(struct stm32_rtc *rtc,
>  static const struct stm32_rtc_data stm32_rtc_data = {
>  	.has_pclk = false,
>  	.need_dbp = true,
> +	.need_accuracy = false,
>  	.regs = {
>  		.tr = 0x00,
>  		.dr = 0x04,
> @@ -566,6 +568,7 @@ static const struct stm32_rtc_data stm32_rtc_data = {
>  static const struct stm32_rtc_data stm32h7_rtc_data = {
>  	.has_pclk = true,
>  	.need_dbp = true,
> +	.need_accuracy = false,
>  	.regs = {
>  		.tr = 0x00,
>  		.dr = 0x04,
> @@ -596,6 +599,7 @@ static void stm32mp1_rtc_clear_events(struct stm32_rtc *rtc,
>  static const struct stm32_rtc_data stm32mp1_data = {
>  	.has_pclk = true,
>  	.need_dbp = false,
> +	.need_accuracy = true,
>  	.regs = {
>  		.tr = 0x00,
>  		.dr = 0x04,
> @@ -636,11 +640,25 @@ static int stm32_rtc_init(struct platform_device *pdev,
>  	pred_a_max = STM32_RTC_PRER_PRED_A >> STM32_RTC_PRER_PRED_A_SHIFT;
>  	pred_s_max = STM32_RTC_PRER_PRED_S >> STM32_RTC_PRER_PRED_S_SHIFT;
>  
> -	for (pred_a = pred_a_max; pred_a + 1 > 0; pred_a--) {
> -		pred_s = (rate / (pred_a + 1)) - 1;
> +	if (rate > (pred_a_max + 1) * (pred_s_max + 1)) {
> +		dev_err(&pdev->dev, "rtc_ck rate is too high: %dHz\n", rate);

What is the expect user action after seeing this message?

> +		return -EINVAL;
> +	}
> +
> +	if (rtc->data->need_accuracy) {
> +		for (pred_a = 0; pred_a <= pred_a_max; pred_a++) {
> +			pred_s = (rate / (pred_a + 1)) - 1;
>  
> -		if (((pred_s + 1) * (pred_a + 1)) == rate)
> -			break;
> +			if (pred_s <= pred_s_max && ((pred_s + 1) * (pred_a + 1)) == rate)
> +				break;
> +		}
> +	} else {
> +		for (pred_a = pred_a_max; pred_a + 1 > 0; pred_a--) {
> +			pred_s = (rate / (pred_a + 1)) - 1;
> +
> +			if (((pred_s + 1) * (pred_a + 1)) == rate)
> +				break;
> +		}
>  	}
>  
>  	/*
> -- 
> 2.25.1
> 

-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com



More information about the linux-arm-kernel mailing list