summaryrefslogtreecommitdiff
path: root/drivers/st
diff options
context:
space:
mode:
authorYann Gautier <yann.gautier@st.com>2019-02-15 17:33:27 +0100
committerYann Gautier <yann.gautier@st.com>2019-02-20 17:34:21 +0100
commitb053a22e8a538d3ee6114c0ce7f25fa49f0302d8 (patch)
treef8818474819c18d8dc75d9c36289deeb386be285 /drivers/st
parent774b4a8190ccb73d9c9deefba0c0fd3878be55ce (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.c78
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(&reg_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 */