diff options
author | Yann Gautier <yann.gautier@st.com> | 2019-02-15 17:33:27 +0100 |
---|---|---|
committer | Yann Gautier <yann.gautier@st.com> | 2019-02-20 17:34:21 +0100 |
commit | b053a22e8a538d3ee6114c0ce7f25fa49f0302d8 (patch) | |
tree | f8818474819c18d8dc75d9c36289deeb386be285 /drivers/st | |
parent | 774b4a8190ccb73d9c9deefba0c0fd3878be55ce (diff) |
stm32mp1: add minimal support for co-processor Cortex-M4
STM32MP1 chip embeds a dual Cortex-A7 and a Cortex-M4.
The support for Cortex-M4 clocks is added when configuring the clock tree.
Some minimal security features to allow communications between A7 and M4
are also added.
Change-Id: I60417e244a476f60a2758f4969700b2684056665
Signed-off-by: Yann Gautier <yann.gautier@st.com>
Diffstat (limited to 'drivers/st')
-rw-r--r-- | drivers/st/clk/stm32mp1_clk.c | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c index c9bb9ff2..11fd6667 100644 --- a/drivers/st/clk/stm32mp1_clk.c +++ b/drivers/st/clk/stm32mp1_clk.c @@ -70,6 +70,7 @@ enum stm32mp1_parent_id { _HCLK2, _CK_PER, _CK_MPU, + _CK_MCU, _USB_PHY_48, _PARENT_NB, _UNKNOWN_ID = 0xff, @@ -93,6 +94,7 @@ enum stm32mp1_parent_sel { _QSPI_SEL, _FMC_SEL, _ASS_SEL, + _MSS_SEL, _USBPHY_SEL, _USBO_SEL, _PARENT_SEL_NB, @@ -117,6 +119,7 @@ enum stm32mp1_div_id { enum stm32mp1_clksrc_id { CLKSRC_MPU, CLKSRC_AXI, + CLKSRC_MCU, CLKSRC_PLL12, CLKSRC_PLL3, CLKSRC_PLL4, @@ -129,6 +132,7 @@ enum stm32mp1_clksrc_id { enum stm32mp1_clkdiv_id { CLKDIV_MPU, CLKDIV_AXI, + CLKDIV_MCU, CLKDIV_APB1, CLKDIV_APB2, CLKDIV_APB3, @@ -272,6 +276,7 @@ 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 }, @@ -412,6 +417,10 @@ static const uint8_t ass_parents[] = { _HSI, _HSE, _PLL2 }; +static const uint8_t mss_parents[] = { + _HSI, _HSE, _CSI, _PLL3 +}; + static const uint8_t usbphy_parents[] = { _HSE_KER, _PLL4_R, _HSE_KER_DIV2 }; @@ -437,6 +446,7 @@ static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = { _CLK_PARENT(_QSPI_SEL, RCC_QSPICKSELR, 0, 0xf, qspi_parents), _CLK_PARENT(_FMC_SEL, RCC_FMCCKSELR, 0, 0xf, fmc_parents), _CLK_PARENT(_ASS_SEL, RCC_ASSCKSELR, 0, 0x3, ass_parents), + _CLK_PARENT(_MSS_SEL, RCC_MSSCKSELR, 0, 0x3, mss_parents), _CLK_PARENT(_USBPHY_SEL, RCC_USBCKSELR, 0, 0x3, usbphy_parents), _CLK_PARENT(_USBO_SEL, RCC_USBCKSELR, 4, 0x1, usbo_parents), }; @@ -483,6 +493,10 @@ static const struct stm32mp1_clk_pll stm32mp1_clk_pll[_PLL_NB] = { }; /* Prescaler table lookups for clock computation */ +/* div = /1 /2 /4 /8 / 16 /64 /128 /512 */ +static const uint8_t stm32mp1_mcu_div[16] = { + 0, 1, 2, 3, 4, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9 +}; /* div = /1 /2 /4 /8 /16 : same divider for PMU and APBX */ #define stm32mp1_mpu_div stm32mp1_mpu_apbx_div @@ -549,6 +563,13 @@ bool stm32mp1_rcc_is_secure(void) return (mmio_read_32(rcc_base + RCC_TZCR) & RCC_TZCR_TZEN) != 0; } +bool stm32mp1_rcc_is_mckprot(void) +{ + uintptr_t rcc_base = stm32mp_rcc_base(); + + return (mmio_read_32(rcc_base + RCC_TZCR) & RCC_TZCR_MCKPROT) != 0; +} + void stm32mp1_clk_rcc_regs_lock(void) { stm32mp1_clk_lock(®_lock); @@ -775,6 +796,51 @@ static unsigned long get_clock_rate(int p) break; } break; + /* MCU sub system */ + case _CK_MCU: + case _PCLK1: + case _PCLK2: + case _PCLK3: + reg = mmio_read_32(rcc_base + RCC_MSSCKSELR); + switch (reg & RCC_SELR_SRC_MASK) { + case RCC_MSSCKSELR_HSI: + clock = stm32mp1_clk_get_fixed(_HSI); + break; + case RCC_MSSCKSELR_HSE: + clock = stm32mp1_clk_get_fixed(_HSE); + break; + case RCC_MSSCKSELR_CSI: + clock = stm32mp1_clk_get_fixed(_CSI); + break; + case RCC_MSSCKSELR_PLL: + clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P); + break; + default: + break; + } + + /* MCU clock divider */ + reg = mmio_read_32(rcc_base + RCC_MCUDIVR); + clock >>= stm32mp1_mcu_div[reg & RCC_MCUDIV_MASK]; + + switch (p) { + case _PCLK1: + reg = mmio_read_32(rcc_base + RCC_APB1DIVR); + clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; + break; + case _PCLK2: + reg = mmio_read_32(rcc_base + RCC_APB2DIVR); + clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; + break; + case _PCLK3: + reg = mmio_read_32(rcc_base + RCC_APB3DIVR); + clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; + break; + case _CK_MCU: + default: + break; + } + break; case _CK_PER: reg = mmio_read_32(rcc_base + RCC_CPERCKSELR); switch (reg & RCC_SELR_SRC_MASK) { @@ -1609,6 +1675,10 @@ int stm32mp1_clk_init(void) if (ret != 0) { return ret; } + ret = stm32mp1_set_clksrc(CLK_MCU_HSI); + if (ret != 0) { + return ret; + } if ((mmio_read_32(rcc_base + RCC_MP_RSTSCLRR) & RCC_MP_RSTSCLRR_MPUP0RSTF) != 0) { @@ -1659,6 +1729,10 @@ int stm32mp1_clk_init(void) if (ret != 0) { return ret; } + ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_MCU], rcc_base + RCC_MCUDIVR); + if (ret != 0) { + return ret; + } ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB1], rcc_base + RCC_APB1DIVR); if (ret != 0) { return ret; @@ -1757,6 +1831,10 @@ int stm32mp1_clk_init(void) if (ret != 0) { return ret; } + ret = stm32mp1_set_clksrc(clksrc[CLKSRC_MCU]); + if (ret != 0) { + return ret; + } stm32mp1_set_rtcsrc(clksrc[CLKSRC_RTC], lse_css); /* Configure PKCK */ |