Browse Source

drivers: stm32mp1 clocks: allow tree lookup for several system clocks

Oscillators, PLLs and some system clocks can be related straight to
a parent clock. Prior this change were only oscillators and few
clocks supported by this look up. This changes adds PLLs and other
system clocks. This enables for flexible use of clock tree exploration
when computing a clock frequency value.

Change-Id: I15ec98023a7095e3120a6954de59a4799d92c66b
Signed-off-by: Etienne Carriere <etienne.carriere@st.com>
pull/1979/head
Etienne Carriere 5 years ago
parent
commit
8fbcd9e421
  1. 84
      drivers/st/clk/stm32mp1_clk.c
  2. 4
      include/drivers/st/stm32mp1_rcc.h

84
drivers/st/clk/stm32mp1_clk.c

@ -106,10 +106,61 @@ enum stm32mp1_parent_sel {
_MCUS_SEL,
_USBPHY_SEL,
_USBO_SEL,
_MPU_SEL,
_PER_SEL,
_PARENT_SEL_NB,
_UNKNOWN_SEL = 0xff,
};
/* State the parent clock ID straight related to a clock */
static const uint8_t parent_id_clock_id[_PARENT_NB] = {
[_HSE] = CK_HSE,
[_HSI] = CK_HSI,
[_CSI] = CK_CSI,
[_LSE] = CK_LSE,
[_LSI] = CK_LSI,
[_I2S_CKIN] = _UNKNOWN_ID,
[_USB_PHY_48] = _UNKNOWN_ID,
[_HSI_KER] = CK_HSI,
[_HSE_KER] = CK_HSE,
[_HSE_KER_DIV2] = CK_HSE_DIV2,
[_CSI_KER] = CK_CSI,
[_PLL1_P] = PLL1_P,
[_PLL1_Q] = PLL1_Q,
[_PLL1_R] = PLL1_R,
[_PLL2_P] = PLL2_P,
[_PLL2_Q] = PLL2_Q,
[_PLL2_R] = PLL2_R,
[_PLL3_P] = PLL3_P,
[_PLL3_Q] = PLL3_Q,
[_PLL3_R] = PLL3_R,
[_PLL4_P] = PLL4_P,
[_PLL4_Q] = PLL4_Q,
[_PLL4_R] = PLL4_R,
[_ACLK] = CK_AXI,
[_PCLK1] = CK_AXI,
[_PCLK2] = CK_AXI,
[_PCLK3] = CK_AXI,
[_PCLK4] = CK_AXI,
[_PCLK5] = CK_AXI,
[_CK_PER] = CK_PER,
[_CK_MPU] = CK_MPU,
[_CK_MCU] = CK_MCU,
};
static unsigned int clock_id2parent_id(unsigned long id)
{
unsigned int n;
for (n = 0U; n < ARRAY_SIZE(parent_id_clock_id); n++) {
if (parent_id_clock_id[n] == id) {
return n;
}
}
return _UNKNOWN_ID;
}
enum stm32mp1_pll_id {
_PLL1,
_PLL2,
@ -281,19 +332,6 @@ struct stm32mp1_clk_pll {
.refclk[3] = (p4), \
}
static const uint8_t stm32mp1_clks[][2] = {
{ CK_PER, _CK_PER },
{ CK_MPU, _CK_MPU },
{ CK_AXI, _ACLK },
{ CK_MCU, _CK_MCU },
{ CK_HSE, _HSE },
{ CK_CSI, _CSI },
{ CK_LSI, _LSI },
{ CK_LSE, _LSE },
{ CK_HSI, _HSI },
{ CK_HSE_DIV2, _HSE_KER_DIV2 },
};
#define NB_GATES ARRAY_SIZE(stm32mp1_clk_gate)
static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = {
@ -440,6 +478,14 @@ static const uint8_t usbo_parents[] = {
_PLL4_R, _USB_PHY_48
};
static const uint8_t mpu_parents[] = {
_HSI, _HSE, _PLL1_P, _PLL1_P /* specific div */
};
static const uint8_t per_parents[] = {
_HSI, _HSE, _CSI,
};
static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = {
_CLK_PARENT_SEL(I2C12, RCC_I2C12CKSELR, i2c12_parents),
_CLK_PARENT_SEL(I2C35, RCC_I2C35CKSELR, i2c35_parents),
@ -448,6 +494,8 @@ static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = {
_CLK_PARENT_SEL(SPI6, RCC_SPI6CKSELR, spi6_parents),
_CLK_PARENT_SEL(UART1, RCC_UART1CKSELR, usart1_parents),
_CLK_PARENT_SEL(RNG1, RCC_RNG1CKSELR, rng1_parents),
_CLK_PARENT_SEL(MPU, RCC_MPCKSELR, mpu_parents),
_CLK_PARENT_SEL(PER, RCC_CPERCKSELR, per_parents),
_CLK_PARENT_SEL(UART6, RCC_UART6CKSELR, uart6_parents),
_CLK_PARENT_SEL(UART24, RCC_UART24CKSELR, uart234578_parents),
_CLK_PARENT_SEL(UART35, RCC_UART35CKSELR, uart234578_parents),
@ -618,16 +666,16 @@ static enum stm32mp1_parent_id stm32mp1_clk_get_fixed_parent(int i)
static int stm32mp1_clk_get_parent(unsigned long id)
{
const struct stm32mp1_clk_sel *sel;
uint32_t j, p_sel;
uint32_t p_sel;
int i;
enum stm32mp1_parent_id p;
enum stm32mp1_parent_sel s;
uintptr_t rcc_base = stm32mp_rcc_base();
for (j = 0U; j < ARRAY_SIZE(stm32mp1_clks); j++) {
if (stm32mp1_clks[j][0] == id) {
return (int)stm32mp1_clks[j][1];
}
/* Few non gateable clock have a static parent ID, find them */
i = (int)clock_id2parent_id(id);
if (i != _UNKNOWN_ID) {
return i;
}
i = stm32mp1_clk_get_gated_id(id);

4
include/drivers/st/stm32mp1_rcc.h

@ -250,6 +250,8 @@
#define RCC_MPCKSELR_HSE 0x00000001
#define RCC_MPCKSELR_PLL 0x00000002
#define RCC_MPCKSELR_PLL_MPUDIV 0x00000003
#define RCC_MPCKSELR_MPUSRC_MASK GENMASK(1, 0)
#define RCC_MPCKSELR_MPUSRC_SHIFT 0
/* Values of RCC_ASSCKSELR register */
#define RCC_ASSCKSELR_HSI 0x00000000
@ -266,6 +268,8 @@
#define RCC_CPERCKSELR_HSI 0x00000000
#define RCC_CPERCKSELR_CSI 0x00000001
#define RCC_CPERCKSELR_HSE 0x00000002
#define RCC_CPERCKSELR_PERSRC_MASK GENMASK(1, 0)
#define RCC_CPERCKSELR_PERSRC_SHIFT 0
/* Used for most of DIVR register: max div for RTC */
#define RCC_DIVR_DIV_MASK GENMASK(5, 0)

Loading…
Cancel
Save