stm32l4: fix various problems with rcc_get* functions
- rcc_get_i2c_clk_freq: Add support by taking RCC_CCIPR2 into account for I2C4. - rcc_get_timer_clk_freq: Add support for LP timers - rcc_get_usart_clk_freq: Fix APB freq used for LPUART1 and UART1, respectively.
This commit is contained in:
committed by
Karl Palsson
parent
a6927e410c
commit
5bcf2a0c35
@@ -90,6 +90,7 @@
|
||||
#define RCC_BDCR MMIO32(RCC_BASE + 0x90)
|
||||
#define RCC_CSR MMIO32(RCC_BASE + 0x94)
|
||||
#define RCC_CRRCR MMIO32(RCC_BASE + 0x98)
|
||||
#define RCC_CCIPR2 MMIO32(RCC_BASE + 0x9C)
|
||||
|
||||
/* --- RCC_CR values ------------------------------------------------------- */
|
||||
|
||||
@@ -636,6 +637,7 @@ Twelve frequency ranges are available: 100 kHz, 200 kHz, 400 kHz, 800 kHz,
|
||||
#define RCC_CCIPR_I2CxSEL_SYS 1
|
||||
#define RCC_CCIPR_I2CxSEL_HSI16 2
|
||||
#define RCC_CCIPR_I2CxSEL_MASK 0x3
|
||||
#define RCC_CCIPR_I2C4SEL_SHIFT 0
|
||||
#define RCC_CCIPR_I2C3SEL_SHIFT 16
|
||||
#define RCC_CCIPR_I2C2SEL_SHIFT 14
|
||||
#define RCC_CCIPR_I2C1SEL_SHIFT 12
|
||||
@@ -663,13 +665,6 @@ Twelve frequency ranges are available: 100 kHz, 200 kHz, 400 kHz, 800 kHz,
|
||||
#define RCC_CCIPR_USART2SEL_SHIFT 2
|
||||
#define RCC_CCIPR_USART1SEL_SHIFT 0
|
||||
|
||||
#define RCC_CCIPR_USART1SEL_APB 0
|
||||
#define RCC_CCIPR_USART1SEL_SYS 1
|
||||
#define RCC_CCIPR_USART1SEL_HSI16 2
|
||||
#define RCC_CCIPR_USART1SEL_LSE 3
|
||||
#define RCC_CCIPR_USART1SEL_SHIFT 0
|
||||
#define RCC_CCIPR_USART1SEL_MASK 0x3
|
||||
|
||||
/* --- RCC_BDCR - Backup domain control register --------------------------- */
|
||||
|
||||
#define RCC_BDCR_LSCOSEL (1 << 25)
|
||||
|
||||
@@ -435,9 +435,10 @@ void rcc_set_rtc_clock_source(enum rcc_osc clk)
|
||||
}
|
||||
}
|
||||
|
||||
/* Helper to calculate the frequency of a UART/I2C based on the apb and clksel value. */
|
||||
static uint32_t rcc_uart_i2c_clksel_freq_hz(uint32_t apb_clk, uint8_t shift) {
|
||||
uint8_t clksel = (RCC_CCIPR >> shift) & RCC_CCIPR_USARTxSEL_MASK;
|
||||
/* Helper to calculate the frequency of a UART/I2C based on the apb and clksel value.
|
||||
* For I2C, clock selection 0b11 is reserved while it specifies LSE for UARTs. */
|
||||
static uint32_t rcc_uart_i2c_clksel_freq_hz(uint32_t apb_clk, uint8_t shift, uint32_t clock_reg) {
|
||||
uint8_t clksel = (clock_reg >> shift) & RCC_CCIPR_USARTxSEL_MASK;
|
||||
uint8_t hpre = (RCC_CFGR >> RCC_CFGR_HPRE_SHIFT) & RCC_CFGR_HPRE_MASK;
|
||||
switch (clksel) {
|
||||
case RCC_CCIPR_USARTxSEL_APB:
|
||||
@@ -446,6 +447,8 @@ static uint32_t rcc_uart_i2c_clksel_freq_hz(uint32_t apb_clk, uint8_t shift) {
|
||||
return rcc_ahb_frequency * rcc_get_div_from_hpre(hpre);
|
||||
case RCC_CCIPR_USARTxSEL_HSI16:
|
||||
return 16000000U;
|
||||
case RCC_CCIPR_USARTxSEL_LSE:
|
||||
return 32768U;
|
||||
}
|
||||
cm3_assert_not_reached();
|
||||
}
|
||||
@@ -458,17 +461,17 @@ uint32_t rcc_get_usart_clk_freq(uint32_t usart)
|
||||
{
|
||||
/* Handle values with selectable clocks. */
|
||||
if (usart == LPUART1_BASE) {
|
||||
return rcc_uart_i2c_clksel_freq_hz(rcc_apb2_frequency, RCC_CCIPR_LPUART1SEL_SHIFT);
|
||||
return rcc_uart_i2c_clksel_freq_hz(rcc_apb1_frequency, RCC_CCIPR_LPUART1SEL_SHIFT, RCC_CCIPR);
|
||||
} else if (usart == USART1_BASE) {
|
||||
return rcc_uart_i2c_clksel_freq_hz(rcc_apb1_frequency, RCC_CCIPR_USART1SEL_SHIFT);
|
||||
return rcc_uart_i2c_clksel_freq_hz(rcc_apb2_frequency, RCC_CCIPR_USART1SEL_SHIFT, RCC_CCIPR);
|
||||
} else if (usart == USART2_BASE) {
|
||||
return rcc_uart_i2c_clksel_freq_hz(rcc_apb1_frequency, RCC_CCIPR_USART2SEL_SHIFT);
|
||||
return rcc_uart_i2c_clksel_freq_hz(rcc_apb1_frequency, RCC_CCIPR_USART2SEL_SHIFT, RCC_CCIPR);
|
||||
} else if (usart == USART3_BASE) {
|
||||
return rcc_uart_i2c_clksel_freq_hz(rcc_apb1_frequency, RCC_CCIPR_USART3SEL_SHIFT);
|
||||
return rcc_uart_i2c_clksel_freq_hz(rcc_apb1_frequency, RCC_CCIPR_USART3SEL_SHIFT, RCC_CCIPR);
|
||||
} else if (usart == UART4_BASE) {
|
||||
return rcc_uart_i2c_clksel_freq_hz(rcc_apb1_frequency, RCC_CCIPR_UART4SEL_SHIFT);
|
||||
return rcc_uart_i2c_clksel_freq_hz(rcc_apb1_frequency, RCC_CCIPR_UART4SEL_SHIFT, RCC_CCIPR);
|
||||
} else { /* USART5 */
|
||||
return rcc_uart_i2c_clksel_freq_hz(rcc_apb1_frequency, RCC_CCIPR_UART5SEL_SHIFT);
|
||||
return rcc_uart_i2c_clksel_freq_hz(rcc_apb1_frequency, RCC_CCIPR_UART5SEL_SHIFT, RCC_CCIPR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -479,7 +482,20 @@ uint32_t rcc_get_usart_clk_freq(uint32_t usart)
|
||||
uint32_t rcc_get_timer_clk_freq(uint32_t timer)
|
||||
{
|
||||
/* Handle APB1 timers, and apply multiplier if necessary. */
|
||||
if (timer >= TIM2_BASE && timer <= TIM7_BASE) {
|
||||
if (timer == LPTIM1_BASE || timer == LPTIM2_BASE) {
|
||||
int shift = (timer == LPTIM1_BASE) ? RCC_CCIPR_LPTIM1SEL_SHIFT : RCC_CCIPR_LPTIM2SEL_SHIFT;
|
||||
uint8_t clksel = (RCC_CCIPR >> shift) & RCC_CCIPR_LPTIMxSEL_MASK;
|
||||
switch (clksel) {
|
||||
case RCC_CCIPR_LPTIMxSEL_APB:
|
||||
return rcc_apb1_frequency;
|
||||
case RCC_CCIPR_LPTIMxSEL_LSI:
|
||||
return 32000U;
|
||||
case RCC_CCIPR_LPTIMxSEL_HSI16:
|
||||
return 16000000U;
|
||||
case RCC_CCIPR_LPTIMxSEL_LSE:
|
||||
return 32768U;
|
||||
}
|
||||
} else if (timer >= TIM2_BASE && timer <= TIM7_BASE) {
|
||||
uint8_t ppre1 = (RCC_CFGR >> RCC_CFGR_PPRE1_SHIFT) & RCC_CFGR_PPRE1_MASK;
|
||||
return (ppre1 == RCC_CFGR_PPRE1_NODIV) ? rcc_apb1_frequency
|
||||
: 2 * rcc_apb1_frequency;
|
||||
@@ -488,6 +504,7 @@ uint32_t rcc_get_timer_clk_freq(uint32_t timer)
|
||||
return (ppre2 == RCC_CFGR_PPRE2_NODIV) ? rcc_apb2_frequency
|
||||
: 2 * rcc_apb2_frequency;
|
||||
}
|
||||
cm3_assert_not_reached();
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
@@ -497,11 +514,13 @@ uint32_t rcc_get_timer_clk_freq(uint32_t timer)
|
||||
uint32_t rcc_get_i2c_clk_freq(uint32_t i2c)
|
||||
{
|
||||
if (i2c == I2C1_BASE) {
|
||||
return rcc_uart_i2c_clksel_freq_hz(rcc_apb1_frequency, RCC_CCIPR_I2C1SEL_SHIFT);
|
||||
return rcc_uart_i2c_clksel_freq_hz(rcc_apb1_frequency, RCC_CCIPR_I2C1SEL_SHIFT, RCC_CCIPR);
|
||||
} else if (i2c == I2C2_BASE) {
|
||||
return rcc_uart_i2c_clksel_freq_hz(rcc_apb1_frequency, RCC_CCIPR_I2C2SEL_SHIFT);
|
||||
} else { /* I2C3 */
|
||||
return rcc_uart_i2c_clksel_freq_hz(rcc_apb1_frequency, RCC_CCIPR_I2C3SEL_SHIFT);
|
||||
return rcc_uart_i2c_clksel_freq_hz(rcc_apb1_frequency, RCC_CCIPR_I2C2SEL_SHIFT, RCC_CCIPR);
|
||||
} else if (i2c == I2C3_BASE) {
|
||||
return rcc_uart_i2c_clksel_freq_hz(rcc_apb1_frequency, RCC_CCIPR_I2C3SEL_SHIFT, RCC_CCIPR);
|
||||
} else { /* I2C4 */
|
||||
return rcc_uart_i2c_clksel_freq_hz(rcc_apb1_frequency, RCC_CCIPR_I2C4SEL_SHIFT, RCC_CCIPR2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user