stm32mp1: add minimal support for co-processor Cortex-M4
authorYann Gautier <yann.gautier@st.com>
Fri, 15 Feb 2019 16:33:27 +0000 (17:33 +0100)
committerYann Gautier <yann.gautier@st.com>
Wed, 20 Feb 2019 16:34:21 +0000 (17:34 +0100)
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>
drivers/st/clk/stm32mp1_clk.c
fdts/stm32mp157a-dk1.dts
fdts/stm32mp157c-ed1.dts
include/drivers/st/stm32mp1_clk.h
include/drivers/st/stm32mp1_rcc.h
plat/st/stm32mp1/bl2_plat_setup.c
plat/st/stm32mp1/stm32mp1_def.h
plat/st/stm32mp1/stm32mp1_security.c

index c9bb9ff2b642773fec936fec5b31a81093b91546..11fd6667de32466331c5fa7587ef76f234bd9558 100644 (file)
@@ -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 */
index 0314171f542011a7121759012dcb025ff6493245..cf0fe2889200ec791e618f2b31ce6cceacfc95ab 100644 (file)
        st,clksrc = <
                CLK_MPU_PLL1P
                CLK_AXI_PLL2P
+               CLK_MCU_PLL3P
                CLK_PLL12_HSE
                CLK_PLL3_HSE
                CLK_PLL4_HSE
        st,clkdiv = <
                1 /*MPU*/
                0 /*AXI*/
+               0 /*MCU*/
                1 /*APB1*/
                1 /*APB2*/
                1 /*APB3*/
index 5d8817f696a0552fdfaa6ace0cd2e4cc4f22137e..0fadffbd6d494472afb72e57a6a0b176c7080e2c 100644 (file)
        st,clksrc = <
                CLK_MPU_PLL1P
                CLK_AXI_PLL2P
+               CLK_MCU_PLL3P
                CLK_PLL12_HSE
                CLK_PLL3_HSE
                CLK_PLL4_HSE
        st,clkdiv = <
                1 /*MPU*/
                0 /*AXI*/
+               0 /*MCU*/
                1 /*APB1*/
                1 /*APB2*/
                1 /*APB3*/
index 1e0d949ac5144003d04a40687edcd1c97d7895ea..7afa5ad84528309d98bd71c9ded6bb71ab28e898 100644 (file)
@@ -13,6 +13,7 @@ int stm32mp1_clk_probe(void);
 int stm32mp1_clk_init(void);
 
 bool stm32mp1_rcc_is_secure(void);
+bool stm32mp1_rcc_is_mckprot(void);
 
 void __stm32mp1_clk_enable(unsigned long id, bool caller_is_secure);
 void __stm32mp1_clk_disable(unsigned long id, bool caller_is_secure);
index 1922c48154666b68e65b0c3d8fbaafc99a470a89..eaa853da3401f7f41b3d29b6ad780090a2c4a859 100644 (file)
 #define RCC_RCK4SELR                   U(0x824)
 #define RCC_TIMG1PRER                  U(0x828)
 #define RCC_TIMG2PRER                  U(0x82C)
+#define RCC_MCUDIVR                    U(0x830)
 #define RCC_APB1DIVR                   U(0x834)
 #define RCC_APB2DIVR                   U(0x838)
 #define RCC_APB3DIVR                   U(0x83C)
 
 /* Values for RCC_TZCR register */
 #define RCC_TZCR_TZEN                  BIT(0)
+#define RCC_TZCR_MCKPROT               BIT(1)
 
 /* Used for most of RCC_<x>SELR registers */
 #define RCC_SELR_SRC_MASK              GENMASK(2, 0)
 #define RCC_APBXDIV_MASK               GENMASK(2, 0)
 #define RCC_MPUDIV_MASK                        GENMASK(2, 0)
 #define RCC_AXIDIV_MASK                        GENMASK(2, 0)
+#define RCC_MCUDIV_MASK                        GENMASK(3, 0)
 
 /* Used for TIMER Prescaler */
 #define RCC_TIMGXPRER_TIMGXPRE         BIT(0)
 
 /* Global Reset Register */
 #define RCC_MP_GRSTCSETR_MPSYSRST      BIT(0)
+#define RCC_MP_GRSTCSETR_MCURST                BIT(1)
 #define RCC_MP_GRSTCSETR_MPUP0RST      BIT(4)
 #define RCC_MP_GRSTCSETR_MPUP1RST      BIT(5)
 
index c7bc39f4e2d05e9c2f1bb80ccf8e0c7d72c4e335..2477954b0fb7e324fd788a0c5be90f96240cb916 100644 (file)
@@ -202,6 +202,9 @@ void bl2_el3_plat_arch_setup(void)
                mmio_clrbits_32(rcc_base + RCC_BDCR, RCC_BDCR_VSWRST);
        }
 
+       /* Disable MCKPROT */
+       mmio_clrbits_32(rcc_base + RCC_TZCR, RCC_TZCR_MCKPROT);
+
        generic_delay_timer_init();
 
        if (stm32mp1_clk_probe() < 0) {
index f0dc575e222d0c652bdd470e170f11b497b932fd..1c897bdf4d0bd22fa3afd6ee61f5acf7afb528db 100644 (file)
@@ -183,6 +183,7 @@ enum ddr_type {
 #define STM32MP1_TZC_BASE              U(0x5C006000)
 
 #define STM32MP1_TZC_A7_ID             U(0)
+#define STM32MP1_TZC_M4_ID             U(1)
 #define STM32MP1_TZC_LCD_ID            U(3)
 #define STM32MP1_TZC_GPU_ID            U(4)
 #define STM32MP1_TZC_MDMA_ID           U(5)
index ebf1587a61e60d7b6e61b925de401a94947748d4..0ad43e43536bd87239c1a024c434a43639062c0a 100644 (file)
@@ -41,6 +41,7 @@ static void init_tzc400(void)
                        TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_GPU_ID) |
                        TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_LCD_ID) |
                        TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_MDMA_ID) |
+                       TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_M4_ID) |
                        TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DMA_ID) |
                        TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_HOST_ID) |
                        TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_OTG_ID) |