1*6b651796SEtienne Carriere // SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0+) 2*6b651796SEtienne Carriere /* 3*6b651796SEtienne Carriere * Copyright (C) 2018-2019, STMicroelectronics 4*6b651796SEtienne Carriere */ 5*6b651796SEtienne Carriere 6*6b651796SEtienne Carriere #include <assert.h> 7*6b651796SEtienne Carriere #include <config.h> 8*6b651796SEtienne Carriere #include <drivers/stm32mp1_rcc.h> 9*6b651796SEtienne Carriere #include <drivers/clk.h> 10*6b651796SEtienne Carriere #include <drivers/clk_dt.h> 11*6b651796SEtienne Carriere #include <dt-bindings/clock/stm32mp1-clks.h> 12*6b651796SEtienne Carriere #include <initcall.h> 13*6b651796SEtienne Carriere #include <io.h> 14*6b651796SEtienne Carriere #include <keep.h> 15*6b651796SEtienne Carriere #include <kernel/dt.h> 16*6b651796SEtienne Carriere #include <kernel/boot.h> 17*6b651796SEtienne Carriere #include <kernel/panic.h> 18*6b651796SEtienne Carriere #include <kernel/spinlock.h> 19*6b651796SEtienne Carriere #include <libfdt.h> 20*6b651796SEtienne Carriere #include <platform_config.h> 21*6b651796SEtienne Carriere #include <stdio.h> 22*6b651796SEtienne Carriere #include <stm32_util.h> 23*6b651796SEtienne Carriere #include <trace.h> 24*6b651796SEtienne Carriere #include <util.h> 25*6b651796SEtienne Carriere 26*6b651796SEtienne Carriere /* Identifiers for root oscillators */ 27*6b651796SEtienne Carriere enum stm32mp_osc_id { 28*6b651796SEtienne Carriere _HSI = 0, 29*6b651796SEtienne Carriere _HSE, 30*6b651796SEtienne Carriere _CSI, 31*6b651796SEtienne Carriere _LSI, 32*6b651796SEtienne Carriere _LSE, 33*6b651796SEtienne Carriere _I2S_CKIN, 34*6b651796SEtienne Carriere _USB_PHY_48, 35*6b651796SEtienne Carriere NB_OSC, 36*6b651796SEtienne Carriere _UNKNOWN_OSC_ID = 0xffU 37*6b651796SEtienne Carriere }; 38*6b651796SEtienne Carriere 39*6b651796SEtienne Carriere /* Identifiers for parent clocks */ 40*6b651796SEtienne Carriere enum stm32mp1_parent_id { 41*6b651796SEtienne Carriere /* 42*6b651796SEtienne Carriere * Oscillators are valid IDs for parent clock and are already 43*6b651796SEtienne Carriere * defined in enum stm32mp_osc_id, ending at NB_OSC - 1. 44*6b651796SEtienne Carriere * This enum defines IDs are the other possible clock parents. 45*6b651796SEtienne Carriere */ 46*6b651796SEtienne Carriere _HSI_KER = NB_OSC, 47*6b651796SEtienne Carriere _HSE_KER, 48*6b651796SEtienne Carriere _HSE_KER_DIV2, 49*6b651796SEtienne Carriere _CSI_KER, 50*6b651796SEtienne Carriere _PLL1_P, 51*6b651796SEtienne Carriere _PLL1_Q, 52*6b651796SEtienne Carriere _PLL1_R, 53*6b651796SEtienne Carriere _PLL2_P, 54*6b651796SEtienne Carriere _PLL2_Q, 55*6b651796SEtienne Carriere _PLL2_R, 56*6b651796SEtienne Carriere _PLL3_P, 57*6b651796SEtienne Carriere _PLL3_Q, 58*6b651796SEtienne Carriere _PLL3_R, 59*6b651796SEtienne Carriere _PLL4_P, 60*6b651796SEtienne Carriere _PLL4_Q, 61*6b651796SEtienne Carriere _PLL4_R, 62*6b651796SEtienne Carriere _ACLK, 63*6b651796SEtienne Carriere _PCLK1, 64*6b651796SEtienne Carriere _PCLK2, 65*6b651796SEtienne Carriere _PCLK3, 66*6b651796SEtienne Carriere _PCLK4, 67*6b651796SEtienne Carriere _PCLK5, 68*6b651796SEtienne Carriere _HCLK5, 69*6b651796SEtienne Carriere _HCLK6, 70*6b651796SEtienne Carriere _HCLK2, 71*6b651796SEtienne Carriere _CK_PER, 72*6b651796SEtienne Carriere _CK_MPU, 73*6b651796SEtienne Carriere _CK_MCU, 74*6b651796SEtienne Carriere _PARENT_NB, 75*6b651796SEtienne Carriere _UNKNOWN_ID = 0xff, 76*6b651796SEtienne Carriere }; 77*6b651796SEtienne Carriere 78*6b651796SEtienne Carriere /* 79*6b651796SEtienne Carriere * Identifiers for parent clock selectors. 80*6b651796SEtienne Carriere * This enum lists only the parent clocks we are interested in. 81*6b651796SEtienne Carriere */ 82*6b651796SEtienne Carriere enum stm32mp1_parent_sel { 83*6b651796SEtienne Carriere _STGEN_SEL, 84*6b651796SEtienne Carriere _I2C46_SEL, 85*6b651796SEtienne Carriere _SPI6_SEL, 86*6b651796SEtienne Carriere _USART1_SEL, 87*6b651796SEtienne Carriere _RNG1_SEL, 88*6b651796SEtienne Carriere _UART6_SEL, 89*6b651796SEtienne Carriere _UART24_SEL, 90*6b651796SEtienne Carriere _UART35_SEL, 91*6b651796SEtienne Carriere _UART78_SEL, 92*6b651796SEtienne Carriere _AXISS_SEL, 93*6b651796SEtienne Carriere _MCUSS_SEL, 94*6b651796SEtienne Carriere _USBPHY_SEL, 95*6b651796SEtienne Carriere _USBO_SEL, 96*6b651796SEtienne Carriere _RTC_SEL, 97*6b651796SEtienne Carriere _PARENT_SEL_NB, 98*6b651796SEtienne Carriere _UNKNOWN_SEL = 0xff, 99*6b651796SEtienne Carriere }; 100*6b651796SEtienne Carriere 101*6b651796SEtienne Carriere static const uint8_t parent_id_clock_id[_PARENT_NB] = { 102*6b651796SEtienne Carriere [_HSE] = CK_HSE, 103*6b651796SEtienne Carriere [_HSI] = CK_HSI, 104*6b651796SEtienne Carriere [_CSI] = CK_CSI, 105*6b651796SEtienne Carriere [_LSE] = CK_LSE, 106*6b651796SEtienne Carriere [_LSI] = CK_LSI, 107*6b651796SEtienne Carriere [_I2S_CKIN] = _UNKNOWN_ID, 108*6b651796SEtienne Carriere [_USB_PHY_48] = _UNKNOWN_ID, 109*6b651796SEtienne Carriere [_HSI_KER] = CK_HSI, 110*6b651796SEtienne Carriere [_HSE_KER] = CK_HSE, 111*6b651796SEtienne Carriere [_HSE_KER_DIV2] = CK_HSE_DIV2, 112*6b651796SEtienne Carriere [_CSI_KER] = CK_CSI, 113*6b651796SEtienne Carriere [_PLL1_P] = PLL1_P, 114*6b651796SEtienne Carriere [_PLL1_Q] = PLL1_Q, 115*6b651796SEtienne Carriere [_PLL1_R] = PLL1_R, 116*6b651796SEtienne Carriere [_PLL2_P] = PLL2_P, 117*6b651796SEtienne Carriere [_PLL2_Q] = PLL2_Q, 118*6b651796SEtienne Carriere [_PLL2_R] = PLL2_R, 119*6b651796SEtienne Carriere [_PLL3_P] = PLL3_P, 120*6b651796SEtienne Carriere [_PLL3_Q] = PLL3_Q, 121*6b651796SEtienne Carriere [_PLL3_R] = PLL3_R, 122*6b651796SEtienne Carriere [_PLL4_P] = PLL4_P, 123*6b651796SEtienne Carriere [_PLL4_Q] = PLL4_Q, 124*6b651796SEtienne Carriere [_PLL4_R] = PLL4_R, 125*6b651796SEtienne Carriere [_ACLK] = CK_AXI, 126*6b651796SEtienne Carriere [_PCLK1] = CK_AXI, 127*6b651796SEtienne Carriere [_PCLK2] = CK_AXI, 128*6b651796SEtienne Carriere [_PCLK3] = CK_AXI, 129*6b651796SEtienne Carriere [_PCLK4] = CK_AXI, 130*6b651796SEtienne Carriere [_PCLK5] = CK_AXI, 131*6b651796SEtienne Carriere [_HCLK5] = CK_AXI, 132*6b651796SEtienne Carriere [_HCLK6] = CK_AXI, 133*6b651796SEtienne Carriere [_HCLK2] = CK_AXI, 134*6b651796SEtienne Carriere [_CK_PER] = CK_PER, 135*6b651796SEtienne Carriere [_CK_MPU] = CK_MPU, 136*6b651796SEtienne Carriere [_CK_MCU] = CK_MCU, 137*6b651796SEtienne Carriere }; 138*6b651796SEtienne Carriere 139*6b651796SEtienne Carriere static enum stm32mp1_parent_id clock_id2parent_id(unsigned long id) 140*6b651796SEtienne Carriere { 141*6b651796SEtienne Carriere size_t n = 0; 142*6b651796SEtienne Carriere 143*6b651796SEtienne Carriere COMPILE_TIME_ASSERT(STM32MP1_LAST_CLK < _UNKNOWN_ID); 144*6b651796SEtienne Carriere 145*6b651796SEtienne Carriere for (n = 0; n < ARRAY_SIZE(parent_id_clock_id); n++) 146*6b651796SEtienne Carriere if (parent_id_clock_id[n] == id) 147*6b651796SEtienne Carriere return (enum stm32mp1_parent_id)n; 148*6b651796SEtienne Carriere 149*6b651796SEtienne Carriere return _UNKNOWN_ID; 150*6b651796SEtienne Carriere } 151*6b651796SEtienne Carriere 152*6b651796SEtienne Carriere /* Identifiers for PLLs and their configuration resources */ 153*6b651796SEtienne Carriere enum stm32mp1_pll_id { 154*6b651796SEtienne Carriere _PLL1, 155*6b651796SEtienne Carriere _PLL2, 156*6b651796SEtienne Carriere _PLL3, 157*6b651796SEtienne Carriere _PLL4, 158*6b651796SEtienne Carriere _PLL_NB 159*6b651796SEtienne Carriere }; 160*6b651796SEtienne Carriere 161*6b651796SEtienne Carriere enum stm32mp1_div_id { 162*6b651796SEtienne Carriere _DIV_P, 163*6b651796SEtienne Carriere _DIV_Q, 164*6b651796SEtienne Carriere _DIV_R, 165*6b651796SEtienne Carriere _DIV_NB, 166*6b651796SEtienne Carriere }; 167*6b651796SEtienne Carriere 168*6b651796SEtienne Carriere enum stm32mp1_plltype { 169*6b651796SEtienne Carriere PLL_800, 170*6b651796SEtienne Carriere PLL_1600, 171*6b651796SEtienne Carriere PLL_TYPE_NB 172*6b651796SEtienne Carriere }; 173*6b651796SEtienne Carriere 174*6b651796SEtienne Carriere /* 175*6b651796SEtienne Carriere * Clock generic gates clocks which state is controlled by a single RCC bit 176*6b651796SEtienne Carriere * 177*6b651796SEtienne Carriere * @offset: RCC register byte offset from RCC base where clock is controlled 178*6b651796SEtienne Carriere * @bit: Bit position in the RCC 32bit register 179*6b651796SEtienne Carriere * @clock_id: Identifier used for the clock in the clock driver API 180*6b651796SEtienne Carriere * @set_clr: Non-null if and only-if RCC register is a CLEAR/SET register 181*6b651796SEtienne Carriere * (CLEAR register is at offset RCC_MP_ENCLRR_OFFSET from SET register) 182*6b651796SEtienne Carriere * @secure: One of N_S or SEC, defined below 183*6b651796SEtienne Carriere * @sel: _UNKNOWN_ID (fixed parent) or reference to parent clock selector 184*6b651796SEtienne Carriere * (8bit storage of ID from enum stm32mp1_parent_sel) 185*6b651796SEtienne Carriere * @fixed: _UNKNOWN_ID (selectable paranet) or reference to parent clock 186*6b651796SEtienne Carriere * (8bit storage of ID from enum stm32mp1_parent_id) 187*6b651796SEtienne Carriere */ 188*6b651796SEtienne Carriere struct stm32mp1_clk_gate { 189*6b651796SEtienne Carriere uint16_t offset; 190*6b651796SEtienne Carriere uint8_t bit; 191*6b651796SEtienne Carriere uint8_t clock_id; 192*6b651796SEtienne Carriere uint8_t set_clr; 193*6b651796SEtienne Carriere uint8_t secure; 194*6b651796SEtienne Carriere uint8_t sel; /* Relates to enum stm32mp1_parent_sel */ 195*6b651796SEtienne Carriere uint8_t fixed; /* Relates to enum stm32mp1_parent_id */ 196*6b651796SEtienne Carriere }; 197*6b651796SEtienne Carriere 198*6b651796SEtienne Carriere /* Parent clock selection: select register info, parent clocks references */ 199*6b651796SEtienne Carriere struct stm32mp1_clk_sel { 200*6b651796SEtienne Carriere uint16_t offset; 201*6b651796SEtienne Carriere uint8_t src; 202*6b651796SEtienne Carriere uint8_t msk; 203*6b651796SEtienne Carriere uint8_t nb_parent; 204*6b651796SEtienne Carriere const uint8_t *parent; 205*6b651796SEtienne Carriere }; 206*6b651796SEtienne Carriere 207*6b651796SEtienne Carriere #define REFCLK_SIZE 4 208*6b651796SEtienne Carriere /* PLL control: type, control register offsets, up-to-4 selectable parent */ 209*6b651796SEtienne Carriere struct stm32mp1_clk_pll { 210*6b651796SEtienne Carriere enum stm32mp1_plltype plltype; 211*6b651796SEtienne Carriere uint16_t rckxselr; 212*6b651796SEtienne Carriere uint16_t pllxcfgr1; 213*6b651796SEtienne Carriere uint16_t pllxcfgr2; 214*6b651796SEtienne Carriere uint16_t pllxfracr; 215*6b651796SEtienne Carriere uint16_t pllxcr; 216*6b651796SEtienne Carriere uint16_t pllxcsgr; 217*6b651796SEtienne Carriere enum stm32mp_osc_id refclk[REFCLK_SIZE]; 218*6b651796SEtienne Carriere }; 219*6b651796SEtienne Carriere 220*6b651796SEtienne Carriere #define N_S 0 /* Non-secure can access RCC interface */ 221*6b651796SEtienne Carriere #define SEC 1 /* RCC[TZEN] protects RCC interface */ 222*6b651796SEtienne Carriere 223*6b651796SEtienne Carriere /* Clocks with selectable source and not set/clr register access */ 224*6b651796SEtienne Carriere #define _CLK_SELEC(_sec, _offset, _bit, _clock_id, _parent_sel) \ 225*6b651796SEtienne Carriere { \ 226*6b651796SEtienne Carriere .offset = (_offset), \ 227*6b651796SEtienne Carriere .bit = (_bit), \ 228*6b651796SEtienne Carriere .clock_id = (_clock_id), \ 229*6b651796SEtienne Carriere .set_clr = 0, \ 230*6b651796SEtienne Carriere .secure = (_sec), \ 231*6b651796SEtienne Carriere .sel = (_parent_sel), \ 232*6b651796SEtienne Carriere .fixed = _UNKNOWN_ID, \ 233*6b651796SEtienne Carriere } 234*6b651796SEtienne Carriere 235*6b651796SEtienne Carriere /* Clocks with fixed source and not set/clr register access */ 236*6b651796SEtienne Carriere #define _CLK_FIXED(_sec, _offset, _bit, _clock_id, _parent) \ 237*6b651796SEtienne Carriere { \ 238*6b651796SEtienne Carriere .offset = (_offset), \ 239*6b651796SEtienne Carriere .bit = (_bit), \ 240*6b651796SEtienne Carriere .clock_id = (_clock_id), \ 241*6b651796SEtienne Carriere .set_clr = 0, \ 242*6b651796SEtienne Carriere .secure = (_sec), \ 243*6b651796SEtienne Carriere .sel = _UNKNOWN_SEL, \ 244*6b651796SEtienne Carriere .fixed = (_parent), \ 245*6b651796SEtienne Carriere } 246*6b651796SEtienne Carriere 247*6b651796SEtienne Carriere /* Clocks with selectable source and set/clr register access */ 248*6b651796SEtienne Carriere #define _CLK_SC_SELEC(_sec, _offset, _bit, _clock_id, _parent_sel) \ 249*6b651796SEtienne Carriere { \ 250*6b651796SEtienne Carriere .offset = (_offset), \ 251*6b651796SEtienne Carriere .bit = (_bit), \ 252*6b651796SEtienne Carriere .clock_id = (_clock_id), \ 253*6b651796SEtienne Carriere .set_clr = 1, \ 254*6b651796SEtienne Carriere .secure = (_sec), \ 255*6b651796SEtienne Carriere .sel = (_parent_sel), \ 256*6b651796SEtienne Carriere .fixed = _UNKNOWN_ID, \ 257*6b651796SEtienne Carriere } 258*6b651796SEtienne Carriere 259*6b651796SEtienne Carriere /* Clocks with fixed source and set/clr register access */ 260*6b651796SEtienne Carriere #define _CLK_SC_FIXED(_sec, _offset, _bit, _clock_id, _parent) \ 261*6b651796SEtienne Carriere { \ 262*6b651796SEtienne Carriere .offset = (_offset), \ 263*6b651796SEtienne Carriere .bit = (_bit), \ 264*6b651796SEtienne Carriere .clock_id = (_clock_id), \ 265*6b651796SEtienne Carriere .set_clr = 1, \ 266*6b651796SEtienne Carriere .secure = (_sec), \ 267*6b651796SEtienne Carriere .sel = _UNKNOWN_SEL, \ 268*6b651796SEtienne Carriere .fixed = (_parent), \ 269*6b651796SEtienne Carriere } 270*6b651796SEtienne Carriere 271*6b651796SEtienne Carriere /* 272*6b651796SEtienne Carriere * Clocks with selectable source and set/clr register access 273*6b651796SEtienne Carriere * and enable bit position defined by a label (argument _bit) 274*6b651796SEtienne Carriere */ 275*6b651796SEtienne Carriere #define _CLK_SC2_SELEC(_sec, _offset, _bit, _clock_id, _parent_sel) \ 276*6b651796SEtienne Carriere { \ 277*6b651796SEtienne Carriere .offset = (_offset), \ 278*6b651796SEtienne Carriere .clock_id = (_clock_id), \ 279*6b651796SEtienne Carriere .bit = _offset ## _ ## _bit ## _POS, \ 280*6b651796SEtienne Carriere .set_clr = 1, \ 281*6b651796SEtienne Carriere .secure = (_sec), \ 282*6b651796SEtienne Carriere .sel = (_parent_sel), \ 283*6b651796SEtienne Carriere .fixed = _UNKNOWN_ID, \ 284*6b651796SEtienne Carriere } 285*6b651796SEtienne Carriere #define _CLK_SC2_FIXED(_sec, _offset, _bit, _clock_id, _parent) \ 286*6b651796SEtienne Carriere { \ 287*6b651796SEtienne Carriere .offset = (_offset), \ 288*6b651796SEtienne Carriere .clock_id = (_clock_id), \ 289*6b651796SEtienne Carriere .bit = _offset ## _ ## _bit ## _POS, \ 290*6b651796SEtienne Carriere .set_clr = 1, \ 291*6b651796SEtienne Carriere .secure = (_sec), \ 292*6b651796SEtienne Carriere .sel = _UNKNOWN_SEL, \ 293*6b651796SEtienne Carriere .fixed = (_parent), \ 294*6b651796SEtienne Carriere } 295*6b651796SEtienne Carriere 296*6b651796SEtienne Carriere #define _CLK_PARENT(idx, _offset, _src, _mask, _parent) \ 297*6b651796SEtienne Carriere [(idx)] = { \ 298*6b651796SEtienne Carriere .offset = (_offset), \ 299*6b651796SEtienne Carriere .src = (_src), \ 300*6b651796SEtienne Carriere .msk = (_mask), \ 301*6b651796SEtienne Carriere .parent = (_parent), \ 302*6b651796SEtienne Carriere .nb_parent = ARRAY_SIZE(_parent) \ 303*6b651796SEtienne Carriere } 304*6b651796SEtienne Carriere 305*6b651796SEtienne Carriere #define _CLK_PLL(_idx, _type, _off1, _off2, _off3, _off4, \ 306*6b651796SEtienne Carriere _off5, _off6, _p1, _p2, _p3, _p4) \ 307*6b651796SEtienne Carriere [(_idx)] = { \ 308*6b651796SEtienne Carriere .plltype = (_type), \ 309*6b651796SEtienne Carriere .rckxselr = (_off1), \ 310*6b651796SEtienne Carriere .pllxcfgr1 = (_off2), \ 311*6b651796SEtienne Carriere .pllxcfgr2 = (_off3), \ 312*6b651796SEtienne Carriere .pllxfracr = (_off4), \ 313*6b651796SEtienne Carriere .pllxcr = (_off5), \ 314*6b651796SEtienne Carriere .pllxcsgr = (_off6), \ 315*6b651796SEtienne Carriere .refclk[0] = (_p1), \ 316*6b651796SEtienne Carriere .refclk[1] = (_p2), \ 317*6b651796SEtienne Carriere .refclk[2] = (_p3), \ 318*6b651796SEtienne Carriere .refclk[3] = (_p4), \ 319*6b651796SEtienne Carriere } 320*6b651796SEtienne Carriere 321*6b651796SEtienne Carriere #define NB_GATES ARRAY_SIZE(stm32mp1_clk_gate) 322*6b651796SEtienne Carriere 323*6b651796SEtienne Carriere static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = { 324*6b651796SEtienne Carriere _CLK_FIXED(SEC, RCC_DDRITFCR, 0, DDRC1, _ACLK), 325*6b651796SEtienne Carriere _CLK_FIXED(SEC, RCC_DDRITFCR, 1, DDRC1LP, _ACLK), 326*6b651796SEtienne Carriere _CLK_FIXED(SEC, RCC_DDRITFCR, 2, DDRC2, _ACLK), 327*6b651796SEtienne Carriere _CLK_FIXED(SEC, RCC_DDRITFCR, 3, DDRC2LP, _ACLK), 328*6b651796SEtienne Carriere _CLK_FIXED(SEC, RCC_DDRITFCR, 4, DDRPHYC, _PLL2_R), 329*6b651796SEtienne Carriere _CLK_FIXED(SEC, RCC_DDRITFCR, 5, DDRPHYCLP, _PLL2_R), 330*6b651796SEtienne Carriere _CLK_FIXED(SEC, RCC_DDRITFCR, 6, DDRCAPB, _PCLK4), 331*6b651796SEtienne Carriere _CLK_FIXED(SEC, RCC_DDRITFCR, 7, DDRCAPBLP, _PCLK4), 332*6b651796SEtienne Carriere _CLK_FIXED(SEC, RCC_DDRITFCR, 8, AXIDCG, _ACLK), 333*6b651796SEtienne Carriere _CLK_FIXED(SEC, RCC_DDRITFCR, 9, DDRPHYCAPB, _PCLK4), 334*6b651796SEtienne Carriere _CLK_FIXED(SEC, RCC_DDRITFCR, 10, DDRPHYCAPBLP, _PCLK4), 335*6b651796SEtienne Carriere 336*6b651796SEtienne Carriere _CLK_SC2_SELEC(SEC, RCC_MP_APB5ENSETR, SPI6EN, SPI6_K, _SPI6_SEL), 337*6b651796SEtienne Carriere _CLK_SC2_SELEC(SEC, RCC_MP_APB5ENSETR, I2C4EN, I2C4_K, _I2C46_SEL), 338*6b651796SEtienne Carriere _CLK_SC2_SELEC(SEC, RCC_MP_APB5ENSETR, I2C6EN, I2C6_K, _I2C46_SEL), 339*6b651796SEtienne Carriere _CLK_SC2_SELEC(SEC, RCC_MP_APB5ENSETR, USART1EN, USART1_K, _USART1_SEL), 340*6b651796SEtienne Carriere _CLK_SC2_FIXED(SEC, RCC_MP_APB5ENSETR, RTCAPBEN, RTCAPB, _PCLK5), 341*6b651796SEtienne Carriere _CLK_SC2_FIXED(SEC, RCC_MP_APB5ENSETR, TZC1EN, TZC1, _PCLK5), 342*6b651796SEtienne Carriere _CLK_SC2_FIXED(SEC, RCC_MP_APB5ENSETR, TZC2EN, TZC2, _PCLK5), 343*6b651796SEtienne Carriere _CLK_SC2_FIXED(SEC, RCC_MP_APB5ENSETR, TZPCEN, TZPC, _PCLK5), 344*6b651796SEtienne Carriere _CLK_SC2_FIXED(SEC, RCC_MP_APB5ENSETR, IWDG1APBEN, IWDG1, _PCLK5), 345*6b651796SEtienne Carriere _CLK_SC2_FIXED(SEC, RCC_MP_APB5ENSETR, BSECEN, BSEC, _PCLK5), 346*6b651796SEtienne Carriere _CLK_SC2_SELEC(SEC, RCC_MP_APB5ENSETR, STGENEN, STGEN_K, _STGEN_SEL), 347*6b651796SEtienne Carriere 348*6b651796SEtienne Carriere _CLK_SC2_FIXED(SEC, RCC_MP_AHB5ENSETR, GPIOZEN, GPIOZ, _HCLK5), 349*6b651796SEtienne Carriere _CLK_SC2_FIXED(SEC, RCC_MP_AHB5ENSETR, CRYP1EN, CRYP1, _HCLK5), 350*6b651796SEtienne Carriere _CLK_SC2_FIXED(SEC, RCC_MP_AHB5ENSETR, HASH1EN, HASH1, _HCLK5), 351*6b651796SEtienne Carriere _CLK_SC2_SELEC(SEC, RCC_MP_AHB5ENSETR, RNG1EN, RNG1_K, _RNG1_SEL), 352*6b651796SEtienne Carriere _CLK_SC2_FIXED(SEC, RCC_MP_AHB5ENSETR, BKPSRAMEN, BKPSRAM, _PCLK5), 353*6b651796SEtienne Carriere 354*6b651796SEtienne Carriere _CLK_SC2_FIXED(SEC, RCC_MP_TZAHB6ENSETR, MDMA, MDMA, _HCLK6), 355*6b651796SEtienne Carriere 356*6b651796SEtienne Carriere _CLK_SELEC(SEC, RCC_BDCR, RCC_BDCR_RTCCKEN_POS, RTC, _RTC_SEL), 357*6b651796SEtienne Carriere 358*6b651796SEtienne Carriere /* Non-secure clocks */ 359*6b651796SEtienne Carriere #ifdef CFG_WITH_NSEC_GPIOS 360*6b651796SEtienne Carriere _CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_ID), 361*6b651796SEtienne Carriere _CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_ID), 362*6b651796SEtienne Carriere _CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 2, GPIOC, _UNKNOWN_ID), 363*6b651796SEtienne Carriere _CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 3, GPIOD, _UNKNOWN_ID), 364*6b651796SEtienne Carriere _CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 4, GPIOE, _UNKNOWN_ID), 365*6b651796SEtienne Carriere _CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 5, GPIOF, _UNKNOWN_ID), 366*6b651796SEtienne Carriere _CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 6, GPIOG, _UNKNOWN_ID), 367*6b651796SEtienne Carriere _CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 7, GPIOH, _UNKNOWN_ID), 368*6b651796SEtienne Carriere _CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 8, GPIOI, _UNKNOWN_ID), 369*6b651796SEtienne Carriere _CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 9, GPIOJ, _UNKNOWN_ID), 370*6b651796SEtienne Carriere _CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 10, GPIOK, _UNKNOWN_ID), 371*6b651796SEtienne Carriere #endif 372*6b651796SEtienne Carriere _CLK_SC_FIXED(N_S, RCC_MP_APB1ENSETR, 6, TIM12_K, _PCLK1), 373*6b651796SEtienne Carriere #ifdef CFG_WITH_NSEC_UARTS 374*6b651796SEtienne Carriere _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 14, USART2_K, _UART24_SEL), 375*6b651796SEtienne Carriere _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 15, USART3_K, _UART35_SEL), 376*6b651796SEtienne Carriere _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 16, UART4_K, _UART24_SEL), 377*6b651796SEtienne Carriere _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 17, UART5_K, _UART35_SEL), 378*6b651796SEtienne Carriere _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 18, UART7_K, _UART78_SEL), 379*6b651796SEtienne Carriere _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 19, UART8_K, _UART78_SEL), 380*6b651796SEtienne Carriere #endif 381*6b651796SEtienne Carriere _CLK_SC_FIXED(N_S, RCC_MP_APB2ENSETR, 2, TIM15_K, _PCLK2), 382*6b651796SEtienne Carriere #ifdef CFG_WITH_NSEC_UARTS 383*6b651796SEtienne Carriere _CLK_SC_SELEC(N_S, RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL), 384*6b651796SEtienne Carriere #endif 385*6b651796SEtienne Carriere _CLK_SC_FIXED(N_S, RCC_MP_APB3ENSETR, 11, SYSCFG, _UNKNOWN_ID), 386*6b651796SEtienne Carriere _CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 8, DDRPERFM, _UNKNOWN_SEL), 387*6b651796SEtienne Carriere _CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 15, IWDG2, _UNKNOWN_SEL), 388*6b651796SEtienne Carriere 389*6b651796SEtienne Carriere _CLK_SELEC(N_S, RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL), 390*6b651796SEtienne Carriere }; 391*6b651796SEtienne Carriere DECLARE_KEEP_PAGER(stm32mp1_clk_gate); 392*6b651796SEtienne Carriere 393*6b651796SEtienne Carriere const uint8_t stm32mp1_clk_on[] = { 394*6b651796SEtienne Carriere CK_HSE, CK_CSI, CK_LSI, CK_LSE, CK_HSI, CK_HSE_DIV2, 395*6b651796SEtienne Carriere PLL1_P, PLL1_Q, PLL1_R, PLL2_P, PLL2_Q, PLL2_R, PLL3_P, PLL3_Q, PLL3_R, 396*6b651796SEtienne Carriere CK_AXI, CK_MPU, CK_MCU, 397*6b651796SEtienne Carriere }; 398*6b651796SEtienne Carriere 399*6b651796SEtienne Carriere /* Parents for secure aware clocks in the xxxSELR value ordering */ 400*6b651796SEtienne Carriere static const uint8_t stgen_parents[] = { 401*6b651796SEtienne Carriere _HSI_KER, _HSE_KER 402*6b651796SEtienne Carriere }; 403*6b651796SEtienne Carriere 404*6b651796SEtienne Carriere static const uint8_t i2c46_parents[] = { 405*6b651796SEtienne Carriere _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER 406*6b651796SEtienne Carriere }; 407*6b651796SEtienne Carriere 408*6b651796SEtienne Carriere static const uint8_t spi6_parents[] = { 409*6b651796SEtienne Carriere _PCLK5, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER, _PLL3_Q 410*6b651796SEtienne Carriere }; 411*6b651796SEtienne Carriere 412*6b651796SEtienne Carriere static const uint8_t usart1_parents[] = { 413*6b651796SEtienne Carriere _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER, _PLL4_Q, _HSE_KER 414*6b651796SEtienne Carriere }; 415*6b651796SEtienne Carriere 416*6b651796SEtienne Carriere static const uint8_t rng1_parents[] = { 417*6b651796SEtienne Carriere _CSI, _PLL4_R, _LSE, _LSI 418*6b651796SEtienne Carriere }; 419*6b651796SEtienne Carriere 420*6b651796SEtienne Carriere /* Parents for (some) non-secure clocks */ 421*6b651796SEtienne Carriere #ifdef CFG_WITH_NSEC_UARTS 422*6b651796SEtienne Carriere static const uint8_t uart6_parents[] = { 423*6b651796SEtienne Carriere _PCLK2, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER 424*6b651796SEtienne Carriere }; 425*6b651796SEtienne Carriere 426*6b651796SEtienne Carriere static const uint8_t uart234578_parents[] = { 427*6b651796SEtienne Carriere _PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER 428*6b651796SEtienne Carriere }; 429*6b651796SEtienne Carriere #endif 430*6b651796SEtienne Carriere 431*6b651796SEtienne Carriere static const uint8_t axiss_parents[] = { 432*6b651796SEtienne Carriere _HSI, _HSE, _PLL2_P 433*6b651796SEtienne Carriere }; 434*6b651796SEtienne Carriere 435*6b651796SEtienne Carriere static const uint8_t mcuss_parents[] = { 436*6b651796SEtienne Carriere _HSI, _HSE, _CSI, _PLL3_P 437*6b651796SEtienne Carriere }; 438*6b651796SEtienne Carriere 439*6b651796SEtienne Carriere static const uint8_t rtc_parents[] = { 440*6b651796SEtienne Carriere _UNKNOWN_ID, _LSE, _LSI, _HSE 441*6b651796SEtienne Carriere }; 442*6b651796SEtienne Carriere 443*6b651796SEtienne Carriere static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = { 444*6b651796SEtienne Carriere /* Secure aware clocks */ 445*6b651796SEtienne Carriere _CLK_PARENT(_STGEN_SEL, RCC_STGENCKSELR, 0, 0x3, stgen_parents), 446*6b651796SEtienne Carriere _CLK_PARENT(_I2C46_SEL, RCC_I2C46CKSELR, 0, 0x7, i2c46_parents), 447*6b651796SEtienne Carriere _CLK_PARENT(_SPI6_SEL, RCC_SPI6CKSELR, 0, 0x7, spi6_parents), 448*6b651796SEtienne Carriere _CLK_PARENT(_USART1_SEL, RCC_UART1CKSELR, 0, 0x7, usart1_parents), 449*6b651796SEtienne Carriere _CLK_PARENT(_RNG1_SEL, RCC_RNG1CKSELR, 0, 0x3, rng1_parents), 450*6b651796SEtienne Carriere _CLK_PARENT(_RTC_SEL, RCC_BDCR, 0, 0x3, rtc_parents), 451*6b651796SEtienne Carriere /* Always non-secure clocks (maybe used in some way in secure world) */ 452*6b651796SEtienne Carriere #ifdef CFG_WITH_NSEC_UARTS 453*6b651796SEtienne Carriere _CLK_PARENT(_UART6_SEL, RCC_UART6CKSELR, 0, 0x7, uart6_parents), 454*6b651796SEtienne Carriere _CLK_PARENT(_UART24_SEL, RCC_UART24CKSELR, 0, 0x7, uart234578_parents), 455*6b651796SEtienne Carriere _CLK_PARENT(_UART35_SEL, RCC_UART35CKSELR, 0, 0x7, uart234578_parents), 456*6b651796SEtienne Carriere _CLK_PARENT(_UART78_SEL, RCC_UART78CKSELR, 0, 0x7, uart234578_parents), 457*6b651796SEtienne Carriere #endif 458*6b651796SEtienne Carriere _CLK_PARENT(_AXISS_SEL, RCC_ASSCKSELR, 0, 0x3, axiss_parents), 459*6b651796SEtienne Carriere _CLK_PARENT(_MCUSS_SEL, RCC_MSSCKSELR, 0, 0x3, mcuss_parents), 460*6b651796SEtienne Carriere }; 461*6b651796SEtienne Carriere 462*6b651796SEtienne Carriere /* PLLNCFGR2 register divider by output */ 463*6b651796SEtienne Carriere static const uint8_t pllncfgr2[_DIV_NB] = { 464*6b651796SEtienne Carriere [_DIV_P] = RCC_PLLNCFGR2_DIVP_SHIFT, 465*6b651796SEtienne Carriere [_DIV_Q] = RCC_PLLNCFGR2_DIVQ_SHIFT, 466*6b651796SEtienne Carriere [_DIV_R] = RCC_PLLNCFGR2_DIVR_SHIFT, 467*6b651796SEtienne Carriere }; 468*6b651796SEtienne Carriere 469*6b651796SEtienne Carriere static const struct stm32mp1_clk_pll stm32mp1_clk_pll[_PLL_NB] = { 470*6b651796SEtienne Carriere _CLK_PLL(_PLL1, PLL_1600, 471*6b651796SEtienne Carriere RCC_RCK12SELR, RCC_PLL1CFGR1, RCC_PLL1CFGR2, 472*6b651796SEtienne Carriere RCC_PLL1FRACR, RCC_PLL1CR, RCC_PLL1CSGR, 473*6b651796SEtienne Carriere _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID), 474*6b651796SEtienne Carriere _CLK_PLL(_PLL2, PLL_1600, 475*6b651796SEtienne Carriere RCC_RCK12SELR, RCC_PLL2CFGR1, RCC_PLL2CFGR2, 476*6b651796SEtienne Carriere RCC_PLL2FRACR, RCC_PLL2CR, RCC_PLL2CSGR, 477*6b651796SEtienne Carriere _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID), 478*6b651796SEtienne Carriere _CLK_PLL(_PLL3, PLL_800, 479*6b651796SEtienne Carriere RCC_RCK3SELR, RCC_PLL3CFGR1, RCC_PLL3CFGR2, 480*6b651796SEtienne Carriere RCC_PLL3FRACR, RCC_PLL3CR, RCC_PLL3CSGR, 481*6b651796SEtienne Carriere _HSI, _HSE, _CSI, _UNKNOWN_OSC_ID), 482*6b651796SEtienne Carriere _CLK_PLL(_PLL4, PLL_800, 483*6b651796SEtienne Carriere RCC_RCK4SELR, RCC_PLL4CFGR1, RCC_PLL4CFGR2, 484*6b651796SEtienne Carriere RCC_PLL4FRACR, RCC_PLL4CR, RCC_PLL4CSGR, 485*6b651796SEtienne Carriere _HSI, _HSE, _CSI, _I2S_CKIN), 486*6b651796SEtienne Carriere }; 487*6b651796SEtienne Carriere 488*6b651796SEtienne Carriere /* Prescaler table lookups for clock computation */ 489*6b651796SEtienne Carriere /* div = /1 /2 /4 /8 / 16 /64 /128 /512 */ 490*6b651796SEtienne Carriere static const uint8_t stm32mp1_mcu_div[16] = { 491*6b651796SEtienne Carriere 0, 1, 2, 3, 4, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9 492*6b651796SEtienne Carriere }; 493*6b651796SEtienne Carriere 494*6b651796SEtienne Carriere /* div = /1 /2 /4 /8 /16 : same divider for PMU and APBX */ 495*6b651796SEtienne Carriere #define stm32mp1_mpu_div stm32mp1_mpu_apbx_div 496*6b651796SEtienne Carriere #define stm32mp1_apbx_div stm32mp1_mpu_apbx_div 497*6b651796SEtienne Carriere static const uint8_t stm32mp1_mpu_apbx_div[8] = { 498*6b651796SEtienne Carriere 0, 1, 2, 3, 4, 4, 4, 4 499*6b651796SEtienne Carriere }; 500*6b651796SEtienne Carriere 501*6b651796SEtienne Carriere /* div = /1 /2 /3 /4 */ 502*6b651796SEtienne Carriere static const uint8_t stm32mp1_axi_div[8] = { 503*6b651796SEtienne Carriere 1, 2, 3, 4, 4, 4, 4, 4 504*6b651796SEtienne Carriere }; 505*6b651796SEtienne Carriere 506*6b651796SEtienne Carriere static const char __maybe_unused *const stm32mp1_clk_parent_name[_PARENT_NB] = { 507*6b651796SEtienne Carriere [_HSI] = "HSI", 508*6b651796SEtienne Carriere [_HSE] = "HSE", 509*6b651796SEtienne Carriere [_CSI] = "CSI", 510*6b651796SEtienne Carriere [_LSI] = "LSI", 511*6b651796SEtienne Carriere [_LSE] = "LSE", 512*6b651796SEtienne Carriere [_I2S_CKIN] = "I2S_CKIN", 513*6b651796SEtienne Carriere [_HSI_KER] = "HSI_KER", 514*6b651796SEtienne Carriere [_HSE_KER] = "HSE_KER", 515*6b651796SEtienne Carriere [_HSE_KER_DIV2] = "HSE_KER_DIV2", 516*6b651796SEtienne Carriere [_CSI_KER] = "CSI_KER", 517*6b651796SEtienne Carriere [_PLL1_P] = "PLL1_P", 518*6b651796SEtienne Carriere [_PLL1_Q] = "PLL1_Q", 519*6b651796SEtienne Carriere [_PLL1_R] = "PLL1_R", 520*6b651796SEtienne Carriere [_PLL2_P] = "PLL2_P", 521*6b651796SEtienne Carriere [_PLL2_Q] = "PLL2_Q", 522*6b651796SEtienne Carriere [_PLL2_R] = "PLL2_R", 523*6b651796SEtienne Carriere [_PLL3_P] = "PLL3_P", 524*6b651796SEtienne Carriere [_PLL3_Q] = "PLL3_Q", 525*6b651796SEtienne Carriere [_PLL3_R] = "PLL3_R", 526*6b651796SEtienne Carriere [_PLL4_P] = "PLL4_P", 527*6b651796SEtienne Carriere [_PLL4_Q] = "PLL4_Q", 528*6b651796SEtienne Carriere [_PLL4_R] = "PLL4_R", 529*6b651796SEtienne Carriere [_ACLK] = "ACLK", 530*6b651796SEtienne Carriere [_PCLK1] = "PCLK1", 531*6b651796SEtienne Carriere [_PCLK2] = "PCLK2", 532*6b651796SEtienne Carriere [_PCLK3] = "PCLK3", 533*6b651796SEtienne Carriere [_PCLK4] = "PCLK4", 534*6b651796SEtienne Carriere [_PCLK5] = "PCLK5", 535*6b651796SEtienne Carriere [_HCLK5] = "HCLK5", 536*6b651796SEtienne Carriere [_HCLK6] = "HCLK6", 537*6b651796SEtienne Carriere [_HCLK2] = "HCLK2", 538*6b651796SEtienne Carriere [_CK_PER] = "CK_PER", 539*6b651796SEtienne Carriere [_CK_MPU] = "CK_MPU", 540*6b651796SEtienne Carriere [_CK_MCU] = "CK_MCU", 541*6b651796SEtienne Carriere [_USB_PHY_48] = "USB_PHY_48", 542*6b651796SEtienne Carriere }; 543*6b651796SEtienne Carriere 544*6b651796SEtienne Carriere /* 545*6b651796SEtienne Carriere * Oscillator frequency in Hz. This array shall be initialized 546*6b651796SEtienne Carriere * according to platform. 547*6b651796SEtienne Carriere */ 548*6b651796SEtienne Carriere static unsigned long stm32mp1_osc[NB_OSC]; 549*6b651796SEtienne Carriere 550*6b651796SEtienne Carriere static unsigned long osc_frequency(enum stm32mp_osc_id idx) 551*6b651796SEtienne Carriere { 552*6b651796SEtienne Carriere if (idx >= ARRAY_SIZE(stm32mp1_osc)) { 553*6b651796SEtienne Carriere DMSG("clk id %d not found", idx); 554*6b651796SEtienne Carriere return 0; 555*6b651796SEtienne Carriere } 556*6b651796SEtienne Carriere 557*6b651796SEtienne Carriere return stm32mp1_osc[idx]; 558*6b651796SEtienne Carriere } 559*6b651796SEtienne Carriere 560*6b651796SEtienne Carriere static const struct stm32mp1_clk_gate *gate_ref(unsigned int idx) 561*6b651796SEtienne Carriere { 562*6b651796SEtienne Carriere return &stm32mp1_clk_gate[idx]; 563*6b651796SEtienne Carriere } 564*6b651796SEtienne Carriere 565*6b651796SEtienne Carriere static const struct stm32mp1_clk_sel *clk_sel_ref(unsigned int idx) 566*6b651796SEtienne Carriere { 567*6b651796SEtienne Carriere return &stm32mp1_clk_sel[idx]; 568*6b651796SEtienne Carriere } 569*6b651796SEtienne Carriere 570*6b651796SEtienne Carriere static const struct stm32mp1_clk_pll *pll_ref(unsigned int idx) 571*6b651796SEtienne Carriere { 572*6b651796SEtienne Carriere return &stm32mp1_clk_pll[idx]; 573*6b651796SEtienne Carriere } 574*6b651796SEtienne Carriere 575*6b651796SEtienne Carriere static int stm32mp1_clk_get_gated_id(unsigned long id) 576*6b651796SEtienne Carriere { 577*6b651796SEtienne Carriere unsigned int i = 0; 578*6b651796SEtienne Carriere 579*6b651796SEtienne Carriere for (i = 0; i < NB_GATES; i++) 580*6b651796SEtienne Carriere if (gate_ref(i)->clock_id == id) 581*6b651796SEtienne Carriere return i; 582*6b651796SEtienne Carriere 583*6b651796SEtienne Carriere DMSG("clk id %lu not found", id); 584*6b651796SEtienne Carriere return -1; 585*6b651796SEtienne Carriere } 586*6b651796SEtienne Carriere 587*6b651796SEtienne Carriere static enum stm32mp1_parent_sel stm32mp1_clk_get_sel(int i) 588*6b651796SEtienne Carriere { 589*6b651796SEtienne Carriere return (enum stm32mp1_parent_sel)gate_ref(i)->sel; 590*6b651796SEtienne Carriere } 591*6b651796SEtienne Carriere 592*6b651796SEtienne Carriere static enum stm32mp1_parent_id stm32mp1_clk_get_fixed_parent(int i) 593*6b651796SEtienne Carriere { 594*6b651796SEtienne Carriere return (enum stm32mp1_parent_id)gate_ref(i)->fixed; 595*6b651796SEtienne Carriere } 596*6b651796SEtienne Carriere 597*6b651796SEtienne Carriere static int stm32mp1_clk_get_parent(unsigned long id) 598*6b651796SEtienne Carriere { 599*6b651796SEtienne Carriere const struct stm32mp1_clk_sel *sel = NULL; 600*6b651796SEtienne Carriere enum stm32mp1_parent_id parent_id = 0; 601*6b651796SEtienne Carriere uint32_t p_sel = 0; 602*6b651796SEtienne Carriere int i = 0; 603*6b651796SEtienne Carriere enum stm32mp1_parent_id p = _UNKNOWN_ID; 604*6b651796SEtienne Carriere enum stm32mp1_parent_sel s = _UNKNOWN_SEL; 605*6b651796SEtienne Carriere vaddr_t rcc_base = stm32_rcc_base(); 606*6b651796SEtienne Carriere 607*6b651796SEtienne Carriere parent_id = clock_id2parent_id(id); 608*6b651796SEtienne Carriere if (parent_id != _UNKNOWN_ID) 609*6b651796SEtienne Carriere return (int)parent_id; 610*6b651796SEtienne Carriere 611*6b651796SEtienne Carriere i = stm32mp1_clk_get_gated_id(id); 612*6b651796SEtienne Carriere if (i < 0) 613*6b651796SEtienne Carriere panic(); 614*6b651796SEtienne Carriere 615*6b651796SEtienne Carriere p = stm32mp1_clk_get_fixed_parent(i); 616*6b651796SEtienne Carriere if (p < _PARENT_NB) 617*6b651796SEtienne Carriere return (int)p; 618*6b651796SEtienne Carriere 619*6b651796SEtienne Carriere s = stm32mp1_clk_get_sel(i); 620*6b651796SEtienne Carriere if (s == _UNKNOWN_SEL) 621*6b651796SEtienne Carriere return -1; 622*6b651796SEtienne Carriere if (s >= _PARENT_SEL_NB) 623*6b651796SEtienne Carriere panic(); 624*6b651796SEtienne Carriere 625*6b651796SEtienne Carriere sel = clk_sel_ref(s); 626*6b651796SEtienne Carriere p_sel = (io_read32(rcc_base + sel->offset) >> sel->src) & sel->msk; 627*6b651796SEtienne Carriere if (p_sel < sel->nb_parent) 628*6b651796SEtienne Carriere return (int)sel->parent[p_sel]; 629*6b651796SEtienne Carriere 630*6b651796SEtienne Carriere DMSG("No parent selected for clk %lu", id); 631*6b651796SEtienne Carriere return -1; 632*6b651796SEtienne Carriere } 633*6b651796SEtienne Carriere 634*6b651796SEtienne Carriere static unsigned long stm32mp1_pll_get_fref(const struct stm32mp1_clk_pll *pll) 635*6b651796SEtienne Carriere { 636*6b651796SEtienne Carriere uint32_t selr = io_read32(stm32_rcc_base() + pll->rckxselr); 637*6b651796SEtienne Carriere uint32_t src = selr & RCC_SELR_REFCLK_SRC_MASK; 638*6b651796SEtienne Carriere 639*6b651796SEtienne Carriere return osc_frequency(pll->refclk[src]); 640*6b651796SEtienne Carriere } 641*6b651796SEtienne Carriere 642*6b651796SEtienne Carriere /* 643*6b651796SEtienne Carriere * pll_get_fvco() : return the VCO or (VCO / 2) frequency for the requested PLL 644*6b651796SEtienne Carriere * - PLL1 & PLL2 => return VCO / 2 with Fpll_y_ck = FVCO / 2 * (DIVy + 1) 645*6b651796SEtienne Carriere * - PLL3 & PLL4 => return VCO with Fpll_y_ck = FVCO / (DIVy + 1) 646*6b651796SEtienne Carriere * => in all cases Fpll_y_ck = pll_get_fvco() / (DIVy + 1) 647*6b651796SEtienne Carriere */ 648*6b651796SEtienne Carriere static unsigned long stm32mp1_pll_get_fvco(const struct stm32mp1_clk_pll *pll) 649*6b651796SEtienne Carriere { 650*6b651796SEtienne Carriere unsigned long refclk = 0; 651*6b651796SEtienne Carriere unsigned long fvco = 0; 652*6b651796SEtienne Carriere uint32_t cfgr1 = 0; 653*6b651796SEtienne Carriere uint32_t fracr = 0; 654*6b651796SEtienne Carriere uint32_t divm = 0; 655*6b651796SEtienne Carriere uint32_t divn = 0; 656*6b651796SEtienne Carriere 657*6b651796SEtienne Carriere cfgr1 = io_read32(stm32_rcc_base() + pll->pllxcfgr1); 658*6b651796SEtienne Carriere fracr = io_read32(stm32_rcc_base() + pll->pllxfracr); 659*6b651796SEtienne Carriere 660*6b651796SEtienne Carriere divm = (cfgr1 & RCC_PLLNCFGR1_DIVM_MASK) >> RCC_PLLNCFGR1_DIVM_SHIFT; 661*6b651796SEtienne Carriere divn = cfgr1 & RCC_PLLNCFGR1_DIVN_MASK; 662*6b651796SEtienne Carriere 663*6b651796SEtienne Carriere refclk = stm32mp1_pll_get_fref(pll); 664*6b651796SEtienne Carriere 665*6b651796SEtienne Carriere /* 666*6b651796SEtienne Carriere * With FRACV : 667*6b651796SEtienne Carriere * Fvco = Fck_ref * ((DIVN + 1) + FRACV / 2^13) / (DIVM + 1) 668*6b651796SEtienne Carriere * Without FRACV 669*6b651796SEtienne Carriere * Fvco = Fck_ref * ((DIVN + 1) / (DIVM + 1) 670*6b651796SEtienne Carriere */ 671*6b651796SEtienne Carriere if (fracr & RCC_PLLNFRACR_FRACLE) { 672*6b651796SEtienne Carriere unsigned long long numerator = 0; 673*6b651796SEtienne Carriere unsigned long long denominator = 0; 674*6b651796SEtienne Carriere uint32_t fracv = (fracr & RCC_PLLNFRACR_FRACV_MASK) >> 675*6b651796SEtienne Carriere RCC_PLLNFRACR_FRACV_SHIFT; 676*6b651796SEtienne Carriere 677*6b651796SEtienne Carriere numerator = (((unsigned long long)divn + 1U) << 13) + fracv; 678*6b651796SEtienne Carriere numerator = refclk * numerator; 679*6b651796SEtienne Carriere denominator = ((unsigned long long)divm + 1U) << 13; 680*6b651796SEtienne Carriere fvco = (unsigned long)(numerator / denominator); 681*6b651796SEtienne Carriere } else { 682*6b651796SEtienne Carriere fvco = (unsigned long)(refclk * (divn + 1U) / (divm + 1U)); 683*6b651796SEtienne Carriere } 684*6b651796SEtienne Carriere 685*6b651796SEtienne Carriere return fvco; 686*6b651796SEtienne Carriere } 687*6b651796SEtienne Carriere 688*6b651796SEtienne Carriere static unsigned long stm32mp1_read_pll_freq(enum stm32mp1_pll_id pll_id, 689*6b651796SEtienne Carriere enum stm32mp1_div_id div_id) 690*6b651796SEtienne Carriere { 691*6b651796SEtienne Carriere const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 692*6b651796SEtienne Carriere unsigned long dfout = 0; 693*6b651796SEtienne Carriere uint32_t cfgr2 = 0; 694*6b651796SEtienne Carriere uint32_t divy = 0; 695*6b651796SEtienne Carriere 696*6b651796SEtienne Carriere if (div_id >= _DIV_NB) 697*6b651796SEtienne Carriere return 0; 698*6b651796SEtienne Carriere 699*6b651796SEtienne Carriere cfgr2 = io_read32(stm32_rcc_base() + pll->pllxcfgr2); 700*6b651796SEtienne Carriere divy = (cfgr2 >> pllncfgr2[div_id]) & RCC_PLLNCFGR2_DIVX_MASK; 701*6b651796SEtienne Carriere 702*6b651796SEtienne Carriere dfout = stm32mp1_pll_get_fvco(pll) / (divy + 1U); 703*6b651796SEtienne Carriere 704*6b651796SEtienne Carriere return dfout; 705*6b651796SEtienne Carriere } 706*6b651796SEtienne Carriere 707*6b651796SEtienne Carriere static unsigned long get_clock_rate(int p) 708*6b651796SEtienne Carriere { 709*6b651796SEtienne Carriere uint32_t reg = 0; 710*6b651796SEtienne Carriere unsigned long clock = 0; 711*6b651796SEtienne Carriere vaddr_t rcc_base = stm32_rcc_base(); 712*6b651796SEtienne Carriere 713*6b651796SEtienne Carriere switch (p) { 714*6b651796SEtienne Carriere case _CK_MPU: 715*6b651796SEtienne Carriere /* MPU sub system */ 716*6b651796SEtienne Carriere reg = io_read32(rcc_base + RCC_MPCKSELR); 717*6b651796SEtienne Carriere switch (reg & RCC_SELR_SRC_MASK) { 718*6b651796SEtienne Carriere case RCC_MPCKSELR_HSI: 719*6b651796SEtienne Carriere clock = osc_frequency(_HSI); 720*6b651796SEtienne Carriere break; 721*6b651796SEtienne Carriere case RCC_MPCKSELR_HSE: 722*6b651796SEtienne Carriere clock = osc_frequency(_HSE); 723*6b651796SEtienne Carriere break; 724*6b651796SEtienne Carriere case RCC_MPCKSELR_PLL: 725*6b651796SEtienne Carriere clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); 726*6b651796SEtienne Carriere break; 727*6b651796SEtienne Carriere case RCC_MPCKSELR_PLL_MPUDIV: 728*6b651796SEtienne Carriere reg = io_read32(rcc_base + RCC_MPCKDIVR); 729*6b651796SEtienne Carriere if (reg & RCC_MPUDIV_MASK) 730*6b651796SEtienne Carriere clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P) >> 731*6b651796SEtienne Carriere stm32mp1_mpu_div[reg & RCC_MPUDIV_MASK]; 732*6b651796SEtienne Carriere else 733*6b651796SEtienne Carriere clock = 0; 734*6b651796SEtienne Carriere break; 735*6b651796SEtienne Carriere default: 736*6b651796SEtienne Carriere break; 737*6b651796SEtienne Carriere } 738*6b651796SEtienne Carriere break; 739*6b651796SEtienne Carriere /* AXI sub system */ 740*6b651796SEtienne Carriere case _ACLK: 741*6b651796SEtienne Carriere case _HCLK2: 742*6b651796SEtienne Carriere case _HCLK5: 743*6b651796SEtienne Carriere case _HCLK6: 744*6b651796SEtienne Carriere case _PCLK4: 745*6b651796SEtienne Carriere case _PCLK5: 746*6b651796SEtienne Carriere reg = io_read32(rcc_base + RCC_ASSCKSELR); 747*6b651796SEtienne Carriere switch (reg & RCC_SELR_SRC_MASK) { 748*6b651796SEtienne Carriere case RCC_ASSCKSELR_HSI: 749*6b651796SEtienne Carriere clock = osc_frequency(_HSI); 750*6b651796SEtienne Carriere break; 751*6b651796SEtienne Carriere case RCC_ASSCKSELR_HSE: 752*6b651796SEtienne Carriere clock = osc_frequency(_HSE); 753*6b651796SEtienne Carriere break; 754*6b651796SEtienne Carriere case RCC_ASSCKSELR_PLL: 755*6b651796SEtienne Carriere clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P); 756*6b651796SEtienne Carriere break; 757*6b651796SEtienne Carriere default: 758*6b651796SEtienne Carriere break; 759*6b651796SEtienne Carriere } 760*6b651796SEtienne Carriere 761*6b651796SEtienne Carriere /* System clock divider */ 762*6b651796SEtienne Carriere reg = io_read32(rcc_base + RCC_AXIDIVR); 763*6b651796SEtienne Carriere clock /= stm32mp1_axi_div[reg & RCC_AXIDIV_MASK]; 764*6b651796SEtienne Carriere 765*6b651796SEtienne Carriere switch (p) { 766*6b651796SEtienne Carriere case _PCLK4: 767*6b651796SEtienne Carriere reg = io_read32(rcc_base + RCC_APB4DIVR); 768*6b651796SEtienne Carriere clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; 769*6b651796SEtienne Carriere break; 770*6b651796SEtienne Carriere case _PCLK5: 771*6b651796SEtienne Carriere reg = io_read32(rcc_base + RCC_APB5DIVR); 772*6b651796SEtienne Carriere clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; 773*6b651796SEtienne Carriere break; 774*6b651796SEtienne Carriere default: 775*6b651796SEtienne Carriere break; 776*6b651796SEtienne Carriere } 777*6b651796SEtienne Carriere break; 778*6b651796SEtienne Carriere /* MCU sub system */ 779*6b651796SEtienne Carriere case _CK_MCU: 780*6b651796SEtienne Carriere case _PCLK1: 781*6b651796SEtienne Carriere case _PCLK2: 782*6b651796SEtienne Carriere case _PCLK3: 783*6b651796SEtienne Carriere reg = io_read32(rcc_base + RCC_MSSCKSELR); 784*6b651796SEtienne Carriere switch (reg & RCC_SELR_SRC_MASK) { 785*6b651796SEtienne Carriere case RCC_MSSCKSELR_HSI: 786*6b651796SEtienne Carriere clock = osc_frequency(_HSI); 787*6b651796SEtienne Carriere break; 788*6b651796SEtienne Carriere case RCC_MSSCKSELR_HSE: 789*6b651796SEtienne Carriere clock = osc_frequency(_HSE); 790*6b651796SEtienne Carriere break; 791*6b651796SEtienne Carriere case RCC_MSSCKSELR_CSI: 792*6b651796SEtienne Carriere clock = osc_frequency(_CSI); 793*6b651796SEtienne Carriere break; 794*6b651796SEtienne Carriere case RCC_MSSCKSELR_PLL: 795*6b651796SEtienne Carriere clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P); 796*6b651796SEtienne Carriere break; 797*6b651796SEtienne Carriere default: 798*6b651796SEtienne Carriere break; 799*6b651796SEtienne Carriere } 800*6b651796SEtienne Carriere 801*6b651796SEtienne Carriere /* MCU clock divider */ 802*6b651796SEtienne Carriere reg = io_read32(rcc_base + RCC_MCUDIVR); 803*6b651796SEtienne Carriere clock >>= stm32mp1_mcu_div[reg & RCC_MCUDIV_MASK]; 804*6b651796SEtienne Carriere 805*6b651796SEtienne Carriere switch (p) { 806*6b651796SEtienne Carriere case _PCLK1: 807*6b651796SEtienne Carriere reg = io_read32(rcc_base + RCC_APB1DIVR); 808*6b651796SEtienne Carriere clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; 809*6b651796SEtienne Carriere break; 810*6b651796SEtienne Carriere case _PCLK2: 811*6b651796SEtienne Carriere reg = io_read32(rcc_base + RCC_APB2DIVR); 812*6b651796SEtienne Carriere clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; 813*6b651796SEtienne Carriere break; 814*6b651796SEtienne Carriere case _PCLK3: 815*6b651796SEtienne Carriere reg = io_read32(rcc_base + RCC_APB3DIVR); 816*6b651796SEtienne Carriere clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; 817*6b651796SEtienne Carriere break; 818*6b651796SEtienne Carriere case _CK_MCU: 819*6b651796SEtienne Carriere default: 820*6b651796SEtienne Carriere break; 821*6b651796SEtienne Carriere } 822*6b651796SEtienne Carriere break; 823*6b651796SEtienne Carriere case _CK_PER: 824*6b651796SEtienne Carriere reg = io_read32(rcc_base + RCC_CPERCKSELR); 825*6b651796SEtienne Carriere switch (reg & RCC_SELR_SRC_MASK) { 826*6b651796SEtienne Carriere case RCC_CPERCKSELR_HSI: 827*6b651796SEtienne Carriere clock = osc_frequency(_HSI); 828*6b651796SEtienne Carriere break; 829*6b651796SEtienne Carriere case RCC_CPERCKSELR_HSE: 830*6b651796SEtienne Carriere clock = osc_frequency(_HSE); 831*6b651796SEtienne Carriere break; 832*6b651796SEtienne Carriere case RCC_CPERCKSELR_CSI: 833*6b651796SEtienne Carriere clock = osc_frequency(_CSI); 834*6b651796SEtienne Carriere break; 835*6b651796SEtienne Carriere default: 836*6b651796SEtienne Carriere break; 837*6b651796SEtienne Carriere } 838*6b651796SEtienne Carriere break; 839*6b651796SEtienne Carriere case _HSI: 840*6b651796SEtienne Carriere case _HSI_KER: 841*6b651796SEtienne Carriere clock = osc_frequency(_HSI); 842*6b651796SEtienne Carriere break; 843*6b651796SEtienne Carriere case _CSI: 844*6b651796SEtienne Carriere case _CSI_KER: 845*6b651796SEtienne Carriere clock = osc_frequency(_CSI); 846*6b651796SEtienne Carriere break; 847*6b651796SEtienne Carriere case _HSE: 848*6b651796SEtienne Carriere case _HSE_KER: 849*6b651796SEtienne Carriere clock = osc_frequency(_HSE); 850*6b651796SEtienne Carriere break; 851*6b651796SEtienne Carriere case _HSE_KER_DIV2: 852*6b651796SEtienne Carriere clock = osc_frequency(_HSE) >> 1; 853*6b651796SEtienne Carriere break; 854*6b651796SEtienne Carriere case _LSI: 855*6b651796SEtienne Carriere clock = osc_frequency(_LSI); 856*6b651796SEtienne Carriere break; 857*6b651796SEtienne Carriere case _LSE: 858*6b651796SEtienne Carriere clock = osc_frequency(_LSE); 859*6b651796SEtienne Carriere break; 860*6b651796SEtienne Carriere /* PLL */ 861*6b651796SEtienne Carriere case _PLL1_P: 862*6b651796SEtienne Carriere clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); 863*6b651796SEtienne Carriere break; 864*6b651796SEtienne Carriere case _PLL1_Q: 865*6b651796SEtienne Carriere clock = stm32mp1_read_pll_freq(_PLL1, _DIV_Q); 866*6b651796SEtienne Carriere break; 867*6b651796SEtienne Carriere case _PLL1_R: 868*6b651796SEtienne Carriere clock = stm32mp1_read_pll_freq(_PLL1, _DIV_R); 869*6b651796SEtienne Carriere break; 870*6b651796SEtienne Carriere case _PLL2_P: 871*6b651796SEtienne Carriere clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P); 872*6b651796SEtienne Carriere break; 873*6b651796SEtienne Carriere case _PLL2_Q: 874*6b651796SEtienne Carriere clock = stm32mp1_read_pll_freq(_PLL2, _DIV_Q); 875*6b651796SEtienne Carriere break; 876*6b651796SEtienne Carriere case _PLL2_R: 877*6b651796SEtienne Carriere clock = stm32mp1_read_pll_freq(_PLL2, _DIV_R); 878*6b651796SEtienne Carriere break; 879*6b651796SEtienne Carriere case _PLL3_P: 880*6b651796SEtienne Carriere clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P); 881*6b651796SEtienne Carriere break; 882*6b651796SEtienne Carriere case _PLL3_Q: 883*6b651796SEtienne Carriere clock = stm32mp1_read_pll_freq(_PLL3, _DIV_Q); 884*6b651796SEtienne Carriere break; 885*6b651796SEtienne Carriere case _PLL3_R: 886*6b651796SEtienne Carriere clock = stm32mp1_read_pll_freq(_PLL3, _DIV_R); 887*6b651796SEtienne Carriere break; 888*6b651796SEtienne Carriere case _PLL4_P: 889*6b651796SEtienne Carriere clock = stm32mp1_read_pll_freq(_PLL4, _DIV_P); 890*6b651796SEtienne Carriere break; 891*6b651796SEtienne Carriere case _PLL4_Q: 892*6b651796SEtienne Carriere clock = stm32mp1_read_pll_freq(_PLL4, _DIV_Q); 893*6b651796SEtienne Carriere break; 894*6b651796SEtienne Carriere case _PLL4_R: 895*6b651796SEtienne Carriere clock = stm32mp1_read_pll_freq(_PLL4, _DIV_R); 896*6b651796SEtienne Carriere break; 897*6b651796SEtienne Carriere /* Other */ 898*6b651796SEtienne Carriere case _USB_PHY_48: 899*6b651796SEtienne Carriere clock = osc_frequency(_USB_PHY_48); 900*6b651796SEtienne Carriere break; 901*6b651796SEtienne Carriere default: 902*6b651796SEtienne Carriere break; 903*6b651796SEtienne Carriere } 904*6b651796SEtienne Carriere 905*6b651796SEtienne Carriere return clock; 906*6b651796SEtienne Carriere } 907*6b651796SEtienne Carriere 908*6b651796SEtienne Carriere static void __clk_enable(const struct stm32mp1_clk_gate *gate) 909*6b651796SEtienne Carriere { 910*6b651796SEtienne Carriere vaddr_t base = stm32_rcc_base(); 911*6b651796SEtienne Carriere uint32_t bit = BIT(gate->bit); 912*6b651796SEtienne Carriere 913*6b651796SEtienne Carriere if (gate->set_clr) 914*6b651796SEtienne Carriere io_write32(base + gate->offset, bit); 915*6b651796SEtienne Carriere else 916*6b651796SEtienne Carriere io_setbits32_stm32shregs(base + gate->offset, bit); 917*6b651796SEtienne Carriere 918*6b651796SEtienne Carriere FMSG("Clock %u has been enabled", gate->clock_id); 919*6b651796SEtienne Carriere } 920*6b651796SEtienne Carriere 921*6b651796SEtienne Carriere static void __clk_disable(const struct stm32mp1_clk_gate *gate) 922*6b651796SEtienne Carriere { 923*6b651796SEtienne Carriere vaddr_t base = stm32_rcc_base(); 924*6b651796SEtienne Carriere uint32_t bit = BIT(gate->bit); 925*6b651796SEtienne Carriere 926*6b651796SEtienne Carriere if (gate->set_clr) 927*6b651796SEtienne Carriere io_write32(base + gate->offset + RCC_MP_ENCLRR_OFFSET, bit); 928*6b651796SEtienne Carriere else 929*6b651796SEtienne Carriere io_clrbits32_stm32shregs(base + gate->offset, bit); 930*6b651796SEtienne Carriere 931*6b651796SEtienne Carriere FMSG("Clock %u has been disabled", gate->clock_id); 932*6b651796SEtienne Carriere } 933*6b651796SEtienne Carriere 934*6b651796SEtienne Carriere static long get_timer_rate(long parent_rate, unsigned int apb_bus) 935*6b651796SEtienne Carriere { 936*6b651796SEtienne Carriere uint32_t timgxpre = 0; 937*6b651796SEtienne Carriere uint32_t apbxdiv = 0; 938*6b651796SEtienne Carriere vaddr_t rcc_base = stm32_rcc_base(); 939*6b651796SEtienne Carriere 940*6b651796SEtienne Carriere switch (apb_bus) { 941*6b651796SEtienne Carriere case 1: 942*6b651796SEtienne Carriere apbxdiv = io_read32(rcc_base + RCC_APB1DIVR) & 943*6b651796SEtienne Carriere RCC_APBXDIV_MASK; 944*6b651796SEtienne Carriere timgxpre = io_read32(rcc_base + RCC_TIMG1PRER) & 945*6b651796SEtienne Carriere RCC_TIMGXPRER_TIMGXPRE; 946*6b651796SEtienne Carriere break; 947*6b651796SEtienne Carriere case 2: 948*6b651796SEtienne Carriere apbxdiv = io_read32(rcc_base + RCC_APB2DIVR) & 949*6b651796SEtienne Carriere RCC_APBXDIV_MASK; 950*6b651796SEtienne Carriere timgxpre = io_read32(rcc_base + RCC_TIMG2PRER) & 951*6b651796SEtienne Carriere RCC_TIMGXPRER_TIMGXPRE; 952*6b651796SEtienne Carriere break; 953*6b651796SEtienne Carriere default: 954*6b651796SEtienne Carriere panic(); 955*6b651796SEtienne Carriere break; 956*6b651796SEtienne Carriere } 957*6b651796SEtienne Carriere 958*6b651796SEtienne Carriere if (apbxdiv == 0) 959*6b651796SEtienne Carriere return parent_rate; 960*6b651796SEtienne Carriere 961*6b651796SEtienne Carriere return parent_rate * (timgxpre + 1) * 2; 962*6b651796SEtienne Carriere } 963*6b651796SEtienne Carriere 964*6b651796SEtienne Carriere static unsigned long _stm32_clock_get_rate(unsigned long id) 965*6b651796SEtienne Carriere { 966*6b651796SEtienne Carriere int p = 0; 967*6b651796SEtienne Carriere unsigned long rate = 0; 968*6b651796SEtienne Carriere 969*6b651796SEtienne Carriere p = stm32mp1_clk_get_parent(id); 970*6b651796SEtienne Carriere if (p < 0) 971*6b651796SEtienne Carriere return 0; 972*6b651796SEtienne Carriere 973*6b651796SEtienne Carriere rate = get_clock_rate(p); 974*6b651796SEtienne Carriere 975*6b651796SEtienne Carriere if ((id >= TIM2_K) && (id <= TIM14_K)) 976*6b651796SEtienne Carriere rate = get_timer_rate(rate, 1); 977*6b651796SEtienne Carriere 978*6b651796SEtienne Carriere if ((id >= TIM1_K) && (id <= TIM17_K)) 979*6b651796SEtienne Carriere rate = get_timer_rate(rate, 2); 980*6b651796SEtienne Carriere 981*6b651796SEtienne Carriere return rate; 982*6b651796SEtienne Carriere } 983*6b651796SEtienne Carriere 984*6b651796SEtienne Carriere /* 985*6b651796SEtienne Carriere * Get the parent ID of the target parent clock, or -1 if no parent found. 986*6b651796SEtienne Carriere */ 987*6b651796SEtienne Carriere static int get_parent_id_parent(unsigned int parent_id) 988*6b651796SEtienne Carriere { 989*6b651796SEtienne Carriere enum stm32mp1_parent_sel s = _UNKNOWN_SEL; 990*6b651796SEtienne Carriere enum stm32mp1_pll_id pll_id = _PLL_NB; 991*6b651796SEtienne Carriere uint32_t p_sel = 0; 992*6b651796SEtienne Carriere 993*6b651796SEtienne Carriere switch (parent_id) { 994*6b651796SEtienne Carriere case _ACLK: 995*6b651796SEtienne Carriere case _PCLK4: 996*6b651796SEtienne Carriere case _PCLK5: 997*6b651796SEtienne Carriere s = _AXISS_SEL; 998*6b651796SEtienne Carriere break; 999*6b651796SEtienne Carriere case _PLL1_P: 1000*6b651796SEtienne Carriere case _PLL1_Q: 1001*6b651796SEtienne Carriere case _PLL1_R: 1002*6b651796SEtienne Carriere pll_id = _PLL1; 1003*6b651796SEtienne Carriere break; 1004*6b651796SEtienne Carriere case _PLL2_P: 1005*6b651796SEtienne Carriere case _PLL2_Q: 1006*6b651796SEtienne Carriere case _PLL2_R: 1007*6b651796SEtienne Carriere pll_id = _PLL2; 1008*6b651796SEtienne Carriere break; 1009*6b651796SEtienne Carriere case _PLL3_P: 1010*6b651796SEtienne Carriere case _PLL3_Q: 1011*6b651796SEtienne Carriere case _PLL3_R: 1012*6b651796SEtienne Carriere pll_id = _PLL3; 1013*6b651796SEtienne Carriere break; 1014*6b651796SEtienne Carriere case _PLL4_P: 1015*6b651796SEtienne Carriere case _PLL4_Q: 1016*6b651796SEtienne Carriere case _PLL4_R: 1017*6b651796SEtienne Carriere pll_id = _PLL4; 1018*6b651796SEtienne Carriere break; 1019*6b651796SEtienne Carriere case _PCLK1: 1020*6b651796SEtienne Carriere case _PCLK2: 1021*6b651796SEtienne Carriere case _HCLK2: 1022*6b651796SEtienne Carriere case _HCLK6: 1023*6b651796SEtienne Carriere case _CK_PER: 1024*6b651796SEtienne Carriere case _CK_MPU: 1025*6b651796SEtienne Carriere case _CK_MCU: 1026*6b651796SEtienne Carriere case _USB_PHY_48: 1027*6b651796SEtienne Carriere /* We do not expected to access these */ 1028*6b651796SEtienne Carriere panic(); 1029*6b651796SEtienne Carriere break; 1030*6b651796SEtienne Carriere default: 1031*6b651796SEtienne Carriere /* Other parents have no parent */ 1032*6b651796SEtienne Carriere return -1; 1033*6b651796SEtienne Carriere } 1034*6b651796SEtienne Carriere 1035*6b651796SEtienne Carriere if (s != _UNKNOWN_SEL) { 1036*6b651796SEtienne Carriere const struct stm32mp1_clk_sel *sel = clk_sel_ref(s); 1037*6b651796SEtienne Carriere vaddr_t rcc_base = stm32_rcc_base(); 1038*6b651796SEtienne Carriere 1039*6b651796SEtienne Carriere p_sel = (io_read32(rcc_base + sel->offset) >> sel->src) & 1040*6b651796SEtienne Carriere sel->msk; 1041*6b651796SEtienne Carriere 1042*6b651796SEtienne Carriere if (p_sel < sel->nb_parent) 1043*6b651796SEtienne Carriere return sel->parent[p_sel]; 1044*6b651796SEtienne Carriere } else { 1045*6b651796SEtienne Carriere const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 1046*6b651796SEtienne Carriere 1047*6b651796SEtienne Carriere p_sel = io_read32(stm32_rcc_base() + pll->rckxselr) & 1048*6b651796SEtienne Carriere RCC_SELR_REFCLK_SRC_MASK; 1049*6b651796SEtienne Carriere 1050*6b651796SEtienne Carriere if (pll->refclk[p_sel] != _UNKNOWN_OSC_ID) 1051*6b651796SEtienne Carriere return pll->refclk[p_sel]; 1052*6b651796SEtienne Carriere } 1053*6b651796SEtienne Carriere 1054*6b651796SEtienne Carriere FMSG("No parent found for %s", stm32mp1_clk_parent_name[parent_id]); 1055*6b651796SEtienne Carriere return -1; 1056*6b651796SEtienne Carriere } 1057*6b651796SEtienne Carriere 1058*6b651796SEtienne Carriere /* We are only interested in knowing if PLL3 shall be secure or not */ 1059*6b651796SEtienne Carriere static void secure_parent_clocks(unsigned long parent_id) 1060*6b651796SEtienne Carriere { 1061*6b651796SEtienne Carriere int grandparent_id = 0; 1062*6b651796SEtienne Carriere 1063*6b651796SEtienne Carriere switch (parent_id) { 1064*6b651796SEtienne Carriere case _ACLK: 1065*6b651796SEtienne Carriere case _HCLK2: 1066*6b651796SEtienne Carriere case _HCLK5: 1067*6b651796SEtienne Carriere case _HCLK6: 1068*6b651796SEtienne Carriere case _PCLK4: 1069*6b651796SEtienne Carriere case _PCLK5: 1070*6b651796SEtienne Carriere /* Intermediate clock mux or clock, go deeper in clock tree */ 1071*6b651796SEtienne Carriere break; 1072*6b651796SEtienne Carriere case _HSI: 1073*6b651796SEtienne Carriere case _HSI_KER: 1074*6b651796SEtienne Carriere case _LSI: 1075*6b651796SEtienne Carriere case _CSI: 1076*6b651796SEtienne Carriere case _CSI_KER: 1077*6b651796SEtienne Carriere case _HSE: 1078*6b651796SEtienne Carriere case _HSE_KER: 1079*6b651796SEtienne Carriere case _HSE_KER_DIV2: 1080*6b651796SEtienne Carriere case _LSE: 1081*6b651796SEtienne Carriere case _PLL1_P: 1082*6b651796SEtienne Carriere case _PLL1_Q: 1083*6b651796SEtienne Carriere case _PLL1_R: 1084*6b651796SEtienne Carriere case _PLL2_P: 1085*6b651796SEtienne Carriere case _PLL2_Q: 1086*6b651796SEtienne Carriere case _PLL2_R: 1087*6b651796SEtienne Carriere /* Always secure clocks, no need to go further */ 1088*6b651796SEtienne Carriere return; 1089*6b651796SEtienne Carriere case _PLL3_P: 1090*6b651796SEtienne Carriere case _PLL3_Q: 1091*6b651796SEtienne Carriere case _PLL3_R: 1092*6b651796SEtienne Carriere /* PLL3 is a shared resource, registered and don't go further */ 1093*6b651796SEtienne Carriere stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3); 1094*6b651796SEtienne Carriere return; 1095*6b651796SEtienne Carriere default: 1096*6b651796SEtienne Carriere DMSG("Cannot lookup parent clock %s", 1097*6b651796SEtienne Carriere stm32mp1_clk_parent_name[parent_id]); 1098*6b651796SEtienne Carriere panic(); 1099*6b651796SEtienne Carriere } 1100*6b651796SEtienne Carriere 1101*6b651796SEtienne Carriere grandparent_id = get_parent_id_parent(parent_id); 1102*6b651796SEtienne Carriere if (grandparent_id >= 0) 1103*6b651796SEtienne Carriere secure_parent_clocks(grandparent_id); 1104*6b651796SEtienne Carriere } 1105*6b651796SEtienne Carriere 1106*6b651796SEtienne Carriere void stm32mp_register_clock_parents_secure(unsigned long clock_id) 1107*6b651796SEtienne Carriere { 1108*6b651796SEtienne Carriere int parent_id = stm32mp1_clk_get_parent(clock_id); 1109*6b651796SEtienne Carriere 1110*6b651796SEtienne Carriere if (parent_id < 0) { 1111*6b651796SEtienne Carriere DMSG("No parent for clock %lu", clock_id); 1112*6b651796SEtienne Carriere return; 1113*6b651796SEtienne Carriere } 1114*6b651796SEtienne Carriere 1115*6b651796SEtienne Carriere secure_parent_clocks(parent_id); 1116*6b651796SEtienne Carriere } 1117*6b651796SEtienne Carriere 1118*6b651796SEtienne Carriere #ifdef CFG_EMBED_DTB 1119*6b651796SEtienne Carriere static const char *stm32mp_osc_node_label[NB_OSC] = { 1120*6b651796SEtienne Carriere [_LSI] = "clk-lsi", 1121*6b651796SEtienne Carriere [_LSE] = "clk-lse", 1122*6b651796SEtienne Carriere [_HSI] = "clk-hsi", 1123*6b651796SEtienne Carriere [_HSE] = "clk-hse", 1124*6b651796SEtienne Carriere [_CSI] = "clk-csi", 1125*6b651796SEtienne Carriere [_I2S_CKIN] = "i2s_ckin", 1126*6b651796SEtienne Carriere [_USB_PHY_48] = "ck_usbo_48m" 1127*6b651796SEtienne Carriere }; 1128*6b651796SEtienne Carriere 1129*6b651796SEtienne Carriere static unsigned int clk_freq_prop(const void *fdt, int node) 1130*6b651796SEtienne Carriere { 1131*6b651796SEtienne Carriere const fdt32_t *cuint = NULL; 1132*6b651796SEtienne Carriere int ret = 0; 1133*6b651796SEtienne Carriere 1134*6b651796SEtienne Carriere /* Disabled clocks report null rate */ 1135*6b651796SEtienne Carriere if (_fdt_get_status(fdt, node) == DT_STATUS_DISABLED) 1136*6b651796SEtienne Carriere return 0; 1137*6b651796SEtienne Carriere 1138*6b651796SEtienne Carriere cuint = fdt_getprop(fdt, node, "clock-frequency", &ret); 1139*6b651796SEtienne Carriere if (!cuint) 1140*6b651796SEtienne Carriere panic(); 1141*6b651796SEtienne Carriere 1142*6b651796SEtienne Carriere return fdt32_to_cpu(*cuint); 1143*6b651796SEtienne Carriere } 1144*6b651796SEtienne Carriere 1145*6b651796SEtienne Carriere static void get_osc_freq_from_dt(const void *fdt) 1146*6b651796SEtienne Carriere { 1147*6b651796SEtienne Carriere enum stm32mp_osc_id idx = _UNKNOWN_OSC_ID; 1148*6b651796SEtienne Carriere int clk_node = fdt_path_offset(fdt, "/clocks"); 1149*6b651796SEtienne Carriere 1150*6b651796SEtienne Carriere if (clk_node < 0) 1151*6b651796SEtienne Carriere panic(); 1152*6b651796SEtienne Carriere 1153*6b651796SEtienne Carriere COMPILE_TIME_ASSERT((int)_HSI == 0); 1154*6b651796SEtienne Carriere for (idx = _HSI; idx < NB_OSC; idx++) { 1155*6b651796SEtienne Carriere const char *name = stm32mp_osc_node_label[idx]; 1156*6b651796SEtienne Carriere int subnode = 0; 1157*6b651796SEtienne Carriere 1158*6b651796SEtienne Carriere fdt_for_each_subnode(subnode, fdt, clk_node) { 1159*6b651796SEtienne Carriere const char *cchar = NULL; 1160*6b651796SEtienne Carriere int ret = 0; 1161*6b651796SEtienne Carriere 1162*6b651796SEtienne Carriere cchar = fdt_get_name(fdt, subnode, &ret); 1163*6b651796SEtienne Carriere if (!cchar) 1164*6b651796SEtienne Carriere panic(); 1165*6b651796SEtienne Carriere 1166*6b651796SEtienne Carriere if (strncmp(cchar, name, (size_t)ret) == 0) { 1167*6b651796SEtienne Carriere stm32mp1_osc[idx] = clk_freq_prop(fdt, subnode); 1168*6b651796SEtienne Carriere 1169*6b651796SEtienne Carriere DMSG("Osc %s: %lu Hz", name, stm32mp1_osc[idx]); 1170*6b651796SEtienne Carriere break; 1171*6b651796SEtienne Carriere } 1172*6b651796SEtienne Carriere } 1173*6b651796SEtienne Carriere 1174*6b651796SEtienne Carriere if (!stm32mp1_osc[idx]) 1175*6b651796SEtienne Carriere DMSG("Osc %s: no frequency info", name); 1176*6b651796SEtienne Carriere } 1177*6b651796SEtienne Carriere } 1178*6b651796SEtienne Carriere #endif /*CFG_EMBED_DTB*/ 1179*6b651796SEtienne Carriere 1180*6b651796SEtienne Carriere static void enable_static_secure_clocks(void) 1181*6b651796SEtienne Carriere { 1182*6b651796SEtienne Carriere unsigned int idx = 0; 1183*6b651796SEtienne Carriere const unsigned long secure_enable[] = { 1184*6b651796SEtienne Carriere DDRC1, DDRC1LP, DDRC2, DDRC2LP, DDRPHYC, DDRPHYCLP, DDRCAPB, 1185*6b651796SEtienne Carriere AXIDCG, DDRPHYCAPB, DDRPHYCAPBLP, TZPC, TZC1, TZC2, STGEN_K, 1186*6b651796SEtienne Carriere BSEC, 1187*6b651796SEtienne Carriere }; 1188*6b651796SEtienne Carriere 1189*6b651796SEtienne Carriere for (idx = 0; idx < ARRAY_SIZE(secure_enable); idx++) { 1190*6b651796SEtienne Carriere stm32_clock_enable(secure_enable[idx]); 1191*6b651796SEtienne Carriere stm32mp_register_clock_parents_secure(secure_enable[idx]); 1192*6b651796SEtienne Carriere } 1193*6b651796SEtienne Carriere 1194*6b651796SEtienne Carriere if (CFG_TEE_CORE_NB_CORE > 1) 1195*6b651796SEtienne Carriere stm32_clock_enable(RTCAPB); 1196*6b651796SEtienne Carriere } 1197*6b651796SEtienne Carriere 1198*6b651796SEtienne Carriere static void __maybe_unused enable_rcc_tzen(void) 1199*6b651796SEtienne Carriere { 1200*6b651796SEtienne Carriere io_setbits32(stm32_rcc_base() + RCC_TZCR, RCC_TZCR_TZEN); 1201*6b651796SEtienne Carriere } 1202*6b651796SEtienne Carriere 1203*6b651796SEtienne Carriere static void __maybe_unused disable_rcc_tzen(void) 1204*6b651796SEtienne Carriere { 1205*6b651796SEtienne Carriere IMSG("RCC is non-secure"); 1206*6b651796SEtienne Carriere io_clrbits32(stm32_rcc_base() + RCC_TZCR, RCC_TZCR_TZEN); 1207*6b651796SEtienne Carriere } 1208*6b651796SEtienne Carriere 1209*6b651796SEtienne Carriere #ifdef CFG_EMBED_DTB 1210*6b651796SEtienne Carriere static TEE_Result stm32mp1_clk_fdt_init(const void *fdt, int node) 1211*6b651796SEtienne Carriere { 1212*6b651796SEtienne Carriere unsigned int i = 0; 1213*6b651796SEtienne Carriere int len = 0; 1214*6b651796SEtienne Carriere int ignored = 0; 1215*6b651796SEtienne Carriere 1216*6b651796SEtienne Carriere get_osc_freq_from_dt(fdt); 1217*6b651796SEtienne Carriere 1218*6b651796SEtienne Carriere /* 1219*6b651796SEtienne Carriere * OP-TEE core is not in charge of configuring clock parenthood. 1220*6b651796SEtienne Carriere * This is expected from an earlier boot stage. Modifying the clock 1221*6b651796SEtienne Carriere * tree parenthood here may jeopardize already configured clocks. 1222*6b651796SEtienne Carriere * The sequence below ignores such DT directives with a friendly 1223*6b651796SEtienne Carriere * debug trace. 1224*6b651796SEtienne Carriere */ 1225*6b651796SEtienne Carriere if (fdt_getprop(fdt, node, "st,clksrc", &len)) { 1226*6b651796SEtienne Carriere DMSG("Ignore source clocks configuration from DT"); 1227*6b651796SEtienne Carriere ignored++; 1228*6b651796SEtienne Carriere } 1229*6b651796SEtienne Carriere if (fdt_getprop(fdt, node, "st,clkdiv", &len)) { 1230*6b651796SEtienne Carriere DMSG("Ignore clock divisors configuration from DT"); 1231*6b651796SEtienne Carriere ignored++; 1232*6b651796SEtienne Carriere } 1233*6b651796SEtienne Carriere if (fdt_getprop(fdt, node, "st,pkcs", &len)) { 1234*6b651796SEtienne Carriere DMSG("Ignore peripheral clocks tree configuration from DT"); 1235*6b651796SEtienne Carriere ignored++; 1236*6b651796SEtienne Carriere } 1237*6b651796SEtienne Carriere for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { 1238*6b651796SEtienne Carriere char name[] = "st,pll@X"; 1239*6b651796SEtienne Carriere 1240*6b651796SEtienne Carriere snprintf(name, sizeof(name), "st,pll@%d", i); 1241*6b651796SEtienne Carriere node = fdt_subnode_offset(fdt, node, name); 1242*6b651796SEtienne Carriere if (node < 0) 1243*6b651796SEtienne Carriere continue; 1244*6b651796SEtienne Carriere 1245*6b651796SEtienne Carriere if (fdt_getprop(fdt, node, "cfg", &len) || 1246*6b651796SEtienne Carriere fdt_getprop(fdt, node, "frac", &len)) { 1247*6b651796SEtienne Carriere DMSG("Ignore PLL%u configurations from DT", i); 1248*6b651796SEtienne Carriere ignored++; 1249*6b651796SEtienne Carriere } 1250*6b651796SEtienne Carriere } 1251*6b651796SEtienne Carriere 1252*6b651796SEtienne Carriere if (ignored != 0) 1253*6b651796SEtienne Carriere IMSG("DT clock tree configurations were ignored"); 1254*6b651796SEtienne Carriere 1255*6b651796SEtienne Carriere return TEE_SUCCESS; 1256*6b651796SEtienne Carriere } 1257*6b651796SEtienne Carriere #endif /*CFG_EMBED_DTB*/ 1258*6b651796SEtienne Carriere 1259*6b651796SEtienne Carriere /* 1260*6b651796SEtienne Carriere * Conversion between clk references and clock gates and clock on internals 1261*6b651796SEtienne Carriere * 1262*6b651796SEtienne Carriere * stm32mp1_clk first cells follow stm32mp1_clk_gate[] ordering. 1263*6b651796SEtienne Carriere * stm32mp1_clk last cells follow stm32mp1_clk_on[] ordering. 1264*6b651796SEtienne Carriere */ 1265*6b651796SEtienne Carriere static struct clk stm32mp1_clk[ARRAY_SIZE(stm32mp1_clk_gate) + 1266*6b651796SEtienne Carriere ARRAY_SIZE(stm32mp1_clk_on)]; 1267*6b651796SEtienne Carriere 1268*6b651796SEtienne Carriere #define CLK_ON_INDEX_OFFSET ((int)ARRAY_SIZE(stm32mp1_clk_gate)) 1269*6b651796SEtienne Carriere 1270*6b651796SEtienne Carriere static bool clk_is_gate(struct clk *clk) 1271*6b651796SEtienne Carriere { 1272*6b651796SEtienne Carriere int clk_index = clk - stm32mp1_clk; 1273*6b651796SEtienne Carriere 1274*6b651796SEtienne Carriere assert(clk_index >= 0 && clk_index < (int)ARRAY_SIZE(stm32mp1_clk)); 1275*6b651796SEtienne Carriere return clk_index < CLK_ON_INDEX_OFFSET; 1276*6b651796SEtienne Carriere } 1277*6b651796SEtienne Carriere 1278*6b651796SEtienne Carriere static unsigned long clk_to_clock_id(struct clk *clk) 1279*6b651796SEtienne Carriere { 1280*6b651796SEtienne Carriere int gate_index = clk - stm32mp1_clk; 1281*6b651796SEtienne Carriere int on_index = gate_index - CLK_ON_INDEX_OFFSET; 1282*6b651796SEtienne Carriere 1283*6b651796SEtienne Carriere if (clk_is_gate(clk)) 1284*6b651796SEtienne Carriere return stm32mp1_clk_gate[gate_index].clock_id; 1285*6b651796SEtienne Carriere 1286*6b651796SEtienne Carriere return stm32mp1_clk_on[on_index]; 1287*6b651796SEtienne Carriere } 1288*6b651796SEtienne Carriere 1289*6b651796SEtienne Carriere static const struct stm32mp1_clk_gate *clk_to_gate_ref(struct clk *clk) 1290*6b651796SEtienne Carriere { 1291*6b651796SEtienne Carriere int gate_index = clk - stm32mp1_clk; 1292*6b651796SEtienne Carriere 1293*6b651796SEtienne Carriere assert(clk_is_gate(clk)); 1294*6b651796SEtienne Carriere 1295*6b651796SEtienne Carriere return stm32mp1_clk_gate + gate_index; 1296*6b651796SEtienne Carriere } 1297*6b651796SEtienne Carriere 1298*6b651796SEtienne Carriere static int clock_id_to_gate_index(unsigned long clock_id) 1299*6b651796SEtienne Carriere { 1300*6b651796SEtienne Carriere size_t n = 0; 1301*6b651796SEtienne Carriere 1302*6b651796SEtienne Carriere for (n = 0; n < ARRAY_SIZE(stm32mp1_clk_gate); n++) 1303*6b651796SEtienne Carriere if (stm32mp1_clk_gate[n].clock_id == clock_id) 1304*6b651796SEtienne Carriere return n; 1305*6b651796SEtienne Carriere 1306*6b651796SEtienne Carriere return -1; 1307*6b651796SEtienne Carriere } 1308*6b651796SEtienne Carriere 1309*6b651796SEtienne Carriere static int clock_id_to_always_on_index(unsigned long clock_id) 1310*6b651796SEtienne Carriere { 1311*6b651796SEtienne Carriere size_t n = 0; 1312*6b651796SEtienne Carriere 1313*6b651796SEtienne Carriere for (n = 0; n < ARRAY_SIZE(stm32mp1_clk_on); n++) 1314*6b651796SEtienne Carriere if (stm32mp1_clk_on[n] == clock_id) 1315*6b651796SEtienne Carriere return n; 1316*6b651796SEtienne Carriere 1317*6b651796SEtienne Carriere return -1; 1318*6b651796SEtienne Carriere } 1319*6b651796SEtienne Carriere 1320*6b651796SEtienne Carriere static struct clk *clock_id_to_clk(unsigned long clock_id) 1321*6b651796SEtienne Carriere { 1322*6b651796SEtienne Carriere int gate_index = clock_id_to_gate_index(clock_id); 1323*6b651796SEtienne Carriere int on_index = clock_id_to_always_on_index(clock_id); 1324*6b651796SEtienne Carriere 1325*6b651796SEtienne Carriere if (gate_index >= 0) 1326*6b651796SEtienne Carriere return stm32mp1_clk + gate_index; 1327*6b651796SEtienne Carriere 1328*6b651796SEtienne Carriere if (on_index >= 0) 1329*6b651796SEtienne Carriere return stm32mp1_clk + CLK_ON_INDEX_OFFSET + on_index; 1330*6b651796SEtienne Carriere 1331*6b651796SEtienne Carriere return NULL; 1332*6b651796SEtienne Carriere } 1333*6b651796SEtienne Carriere 1334*6b651796SEtienne Carriere #if CFG_TEE_CORE_LOG_LEVEL >= TRACE_DEBUG 1335*6b651796SEtienne Carriere struct clk_name { 1336*6b651796SEtienne Carriere unsigned int clock_id; 1337*6b651796SEtienne Carriere const char *name; 1338*6b651796SEtienne Carriere }; 1339*6b651796SEtienne Carriere 1340*6b651796SEtienne Carriere #define CLOCK_NAME(_binding, _name) \ 1341*6b651796SEtienne Carriere { .clock_id = (_binding), .name = (_name) } 1342*6b651796SEtienne Carriere 1343*6b651796SEtienne Carriere /* Store names only for some clocks */ 1344*6b651796SEtienne Carriere const struct clk_name exposed_clk_name[] = { 1345*6b651796SEtienne Carriere /* Clocks used by platform drivers not yet probed from DT */ 1346*6b651796SEtienne Carriere CLOCK_NAME(CK_DBG, "dbg"), 1347*6b651796SEtienne Carriere CLOCK_NAME(CK_MCU, "mcu"), 1348*6b651796SEtienne Carriere CLOCK_NAME(RTCAPB, "rtcapb"), 1349*6b651796SEtienne Carriere CLOCK_NAME(BKPSRAM, "bkpsram"), 1350*6b651796SEtienne Carriere CLOCK_NAME(RTC, "rtc"), 1351*6b651796SEtienne Carriere CLOCK_NAME(CRYP1, "crpy1"), 1352*6b651796SEtienne Carriere CLOCK_NAME(SYSCFG, "syscfg"), 1353*6b651796SEtienne Carriere CLOCK_NAME(GPIOA, "gpioa"), 1354*6b651796SEtienne Carriere CLOCK_NAME(GPIOB, "gpiob"), 1355*6b651796SEtienne Carriere CLOCK_NAME(GPIOC, "gpioc"), 1356*6b651796SEtienne Carriere CLOCK_NAME(GPIOD, "gpiod"), 1357*6b651796SEtienne Carriere CLOCK_NAME(GPIOE, "gpioe"), 1358*6b651796SEtienne Carriere CLOCK_NAME(GPIOF, "gpiof"), 1359*6b651796SEtienne Carriere CLOCK_NAME(GPIOG, "gpiog"), 1360*6b651796SEtienne Carriere CLOCK_NAME(GPIOH, "gpioh"), 1361*6b651796SEtienne Carriere CLOCK_NAME(GPIOI, "gpioi"), 1362*6b651796SEtienne Carriere CLOCK_NAME(GPIOJ, "gpioj"), 1363*6b651796SEtienne Carriere CLOCK_NAME(GPIOK, "gpiok"), 1364*6b651796SEtienne Carriere CLOCK_NAME(GPIOZ, "gpioz"), 1365*6b651796SEtienne Carriere /* Clock exposed by SCMI. SCMI clock fmro DT bindings to come... */ 1366*6b651796SEtienne Carriere CLOCK_NAME(CK_HSE, "hse"), 1367*6b651796SEtienne Carriere CLOCK_NAME(CK_HSI, "hsi"), 1368*6b651796SEtienne Carriere CLOCK_NAME(CK_CSI, "csi"), 1369*6b651796SEtienne Carriere CLOCK_NAME(CK_LSE, "lse"), 1370*6b651796SEtienne Carriere CLOCK_NAME(CK_LSI, "lsi"), 1371*6b651796SEtienne Carriere CLOCK_NAME(PLL2_Q, "pll2q"), 1372*6b651796SEtienne Carriere CLOCK_NAME(PLL2_R, "pll2r"), 1373*6b651796SEtienne Carriere CLOCK_NAME(PLL3_Q, "pll3q"), 1374*6b651796SEtienne Carriere CLOCK_NAME(PLL3_R, "pll3r"), 1375*6b651796SEtienne Carriere CLOCK_NAME(CRYP1, "cryp1"), 1376*6b651796SEtienne Carriere CLOCK_NAME(HASH1, "hash1"), 1377*6b651796SEtienne Carriere CLOCK_NAME(I2C4_K, "i2c4"), 1378*6b651796SEtienne Carriere CLOCK_NAME(I2C6_K, "i2c6"), 1379*6b651796SEtienne Carriere CLOCK_NAME(IWDG1, "iwdg"), 1380*6b651796SEtienne Carriere CLOCK_NAME(RNG1_K, "rng1"), 1381*6b651796SEtienne Carriere CLOCK_NAME(SPI6_K, "spi6"), 1382*6b651796SEtienne Carriere CLOCK_NAME(USART1_K, "usart1"), 1383*6b651796SEtienne Carriere CLOCK_NAME(CK_MCU, "mcu"), 1384*6b651796SEtienne Carriere }; 1385*6b651796SEtienne Carriere DECLARE_KEEP_PAGER(exposed_clk_name); 1386*6b651796SEtienne Carriere 1387*6b651796SEtienne Carriere static const char *clk_op_get_name(struct clk *clk) 1388*6b651796SEtienne Carriere { 1389*6b651796SEtienne Carriere unsigned long clock_id = clk_to_clock_id(clk); 1390*6b651796SEtienne Carriere size_t n = 0; 1391*6b651796SEtienne Carriere 1392*6b651796SEtienne Carriere for (n = 0; n < ARRAY_SIZE(exposed_clk_name); n++) 1393*6b651796SEtienne Carriere if (exposed_clk_name[n].clock_id == clock_id) 1394*6b651796SEtienne Carriere return exposed_clk_name[n].name; 1395*6b651796SEtienne Carriere 1396*6b651796SEtienne Carriere return NULL; 1397*6b651796SEtienne Carriere } 1398*6b651796SEtienne Carriere #else 1399*6b651796SEtienne Carriere static const char *clk_op_get_name(struct clk *clk __unused) 1400*6b651796SEtienne Carriere { 1401*6b651796SEtienne Carriere return NULL; 1402*6b651796SEtienne Carriere } 1403*6b651796SEtienne Carriere #endif /*CFG_TEE_CORE_LOG_LEVEL*/ 1404*6b651796SEtienne Carriere 1405*6b651796SEtienne Carriere static unsigned long clk_op_compute_rate(struct clk *clk, 1406*6b651796SEtienne Carriere unsigned long parent_rate __unused) 1407*6b651796SEtienne Carriere { 1408*6b651796SEtienne Carriere return _stm32_clock_get_rate(clk_to_clock_id(clk)); 1409*6b651796SEtienne Carriere } 1410*6b651796SEtienne Carriere 1411*6b651796SEtienne Carriere static TEE_Result clk_op_enable(struct clk *clk) 1412*6b651796SEtienne Carriere { 1413*6b651796SEtienne Carriere if (clk_is_gate(clk)) 1414*6b651796SEtienne Carriere __clk_enable(clk_to_gate_ref(clk)); 1415*6b651796SEtienne Carriere 1416*6b651796SEtienne Carriere return TEE_SUCCESS; 1417*6b651796SEtienne Carriere } 1418*6b651796SEtienne Carriere DECLARE_KEEP_PAGER(clk_op_enable); 1419*6b651796SEtienne Carriere 1420*6b651796SEtienne Carriere static void clk_op_disable(struct clk *clk) 1421*6b651796SEtienne Carriere { 1422*6b651796SEtienne Carriere if (clk_is_gate(clk)) 1423*6b651796SEtienne Carriere __clk_disable(clk_to_gate_ref(clk)); 1424*6b651796SEtienne Carriere } 1425*6b651796SEtienne Carriere DECLARE_KEEP_PAGER(clk_op_disable); 1426*6b651796SEtienne Carriere 1427*6b651796SEtienne Carriere /* This variable is weak to break its dependency chain when linked as unpaged */ 1428*6b651796SEtienne Carriere const struct clk_ops stm32mp1_clk_ops 1429*6b651796SEtienne Carriere __weak __rodata_unpaged("stm32mp1_clk_ops") = { 1430*6b651796SEtienne Carriere .enable = clk_op_enable, 1431*6b651796SEtienne Carriere .disable = clk_op_disable, 1432*6b651796SEtienne Carriere .get_rate = clk_op_compute_rate, 1433*6b651796SEtienne Carriere }; 1434*6b651796SEtienne Carriere 1435*6b651796SEtienne Carriere static TEE_Result register_stm32mp1_clocks(void) 1436*6b651796SEtienne Carriere { 1437*6b651796SEtienne Carriere TEE_Result res = TEE_ERROR_GENERIC; 1438*6b651796SEtienne Carriere size_t n = 0; 1439*6b651796SEtienne Carriere 1440*6b651796SEtienne Carriere for (n = 0; n < ARRAY_SIZE(stm32mp1_clk); n++) { 1441*6b651796SEtienne Carriere stm32mp1_clk[n].ops = &stm32mp1_clk_ops; 1442*6b651796SEtienne Carriere stm32mp1_clk[n].name = clk_op_get_name(stm32mp1_clk + n); 1443*6b651796SEtienne Carriere refcount_set(&stm32mp1_clk[n].enabled_count, 0); 1444*6b651796SEtienne Carriere 1445*6b651796SEtienne Carriere res = clk_register(stm32mp1_clk + n); 1446*6b651796SEtienne Carriere if (res) 1447*6b651796SEtienne Carriere return res; 1448*6b651796SEtienne Carriere } 1449*6b651796SEtienne Carriere 1450*6b651796SEtienne Carriere return TEE_SUCCESS; 1451*6b651796SEtienne Carriere } 1452*6b651796SEtienne Carriere 1453*6b651796SEtienne Carriere /* Route platform legacy clock functions to clk driver functions */ 1454*6b651796SEtienne Carriere bool stm32_clock_is_enabled(unsigned long clock_id) 1455*6b651796SEtienne Carriere { 1456*6b651796SEtienne Carriere struct clk *clk = clock_id_to_clk(clock_id); 1457*6b651796SEtienne Carriere 1458*6b651796SEtienne Carriere assert(clk); 1459*6b651796SEtienne Carriere return clk_is_enabled(clk); 1460*6b651796SEtienne Carriere } 1461*6b651796SEtienne Carriere 1462*6b651796SEtienne Carriere void stm32_clock_enable(unsigned long clock_id) 1463*6b651796SEtienne Carriere { 1464*6b651796SEtienne Carriere struct clk *clk = clock_id_to_clk(clock_id); 1465*6b651796SEtienne Carriere TEE_Result __maybe_unused res = TEE_ERROR_GENERIC; 1466*6b651796SEtienne Carriere 1467*6b651796SEtienne Carriere assert(clk); 1468*6b651796SEtienne Carriere res = clk_enable(clk); 1469*6b651796SEtienne Carriere assert(!res); 1470*6b651796SEtienne Carriere } 1471*6b651796SEtienne Carriere 1472*6b651796SEtienne Carriere void stm32_clock_disable(unsigned long clock_id) 1473*6b651796SEtienne Carriere { 1474*6b651796SEtienne Carriere struct clk *clk = clock_id_to_clk(clock_id); 1475*6b651796SEtienne Carriere 1476*6b651796SEtienne Carriere assert(clk); 1477*6b651796SEtienne Carriere clk_disable(clk); 1478*6b651796SEtienne Carriere } 1479*6b651796SEtienne Carriere 1480*6b651796SEtienne Carriere unsigned long stm32_clock_get_rate(unsigned long clock_id) 1481*6b651796SEtienne Carriere { 1482*6b651796SEtienne Carriere struct clk *clk = clock_id_to_clk(clock_id); 1483*6b651796SEtienne Carriere 1484*6b651796SEtienne Carriere assert(clk); 1485*6b651796SEtienne Carriere return clk_get_rate(clk); 1486*6b651796SEtienne Carriere } 1487*6b651796SEtienne Carriere 1488*6b651796SEtienne Carriere #ifdef CFG_DRIVERS_CLK_DT 1489*6b651796SEtienne Carriere static struct clk *stm32mp1_clk_dt_get_clk(struct dt_driver_phandle_args *pargs, 1490*6b651796SEtienne Carriere void *data __unused, TEE_Result *res) 1491*6b651796SEtienne Carriere { 1492*6b651796SEtienne Carriere unsigned long clock_id = pargs->args[0]; 1493*6b651796SEtienne Carriere struct clk *clk = NULL; 1494*6b651796SEtienne Carriere 1495*6b651796SEtienne Carriere *res = TEE_ERROR_BAD_PARAMETERS; 1496*6b651796SEtienne Carriere 1497*6b651796SEtienne Carriere if (pargs->args_count != 1) 1498*6b651796SEtienne Carriere return NULL; 1499*6b651796SEtienne Carriere 1500*6b651796SEtienne Carriere clk = clock_id_to_clk(clock_id); 1501*6b651796SEtienne Carriere if (!clk) 1502*6b651796SEtienne Carriere return NULL; 1503*6b651796SEtienne Carriere 1504*6b651796SEtienne Carriere *res = TEE_SUCCESS; 1505*6b651796SEtienne Carriere return clk; 1506*6b651796SEtienne Carriere } 1507*6b651796SEtienne Carriere 1508*6b651796SEtienne Carriere /* Non-null reference for compat data */ 1509*6b651796SEtienne Carriere static const uint8_t non_secure_rcc; 1510*6b651796SEtienne Carriere 1511*6b651796SEtienne Carriere static TEE_Result stm32mp1_clock_provider_probe(const void *fdt, int offs, 1512*6b651796SEtienne Carriere const void *compat_data) 1513*6b651796SEtienne Carriere { 1514*6b651796SEtienne Carriere TEE_Result res = TEE_ERROR_GENERIC; 1515*6b651796SEtienne Carriere 1516*6b651796SEtienne Carriere if (compat_data == &non_secure_rcc) 1517*6b651796SEtienne Carriere disable_rcc_tzen(); 1518*6b651796SEtienne Carriere else 1519*6b651796SEtienne Carriere enable_rcc_tzen(); 1520*6b651796SEtienne Carriere 1521*6b651796SEtienne Carriere res = stm32mp1_clk_fdt_init(fdt, offs); 1522*6b651796SEtienne Carriere if (res) { 1523*6b651796SEtienne Carriere EMSG("Failed to initialize clocks from DT: %#"PRIx32, res); 1524*6b651796SEtienne Carriere panic(); 1525*6b651796SEtienne Carriere } 1526*6b651796SEtienne Carriere 1527*6b651796SEtienne Carriere res = register_stm32mp1_clocks(); 1528*6b651796SEtienne Carriere if (res) { 1529*6b651796SEtienne Carriere EMSG("Failed to register clocks: %#"PRIx32, res); 1530*6b651796SEtienne Carriere panic(); 1531*6b651796SEtienne Carriere } 1532*6b651796SEtienne Carriere 1533*6b651796SEtienne Carriere res = clk_dt_register_clk_provider(fdt, offs, stm32mp1_clk_dt_get_clk, 1534*6b651796SEtienne Carriere NULL); 1535*6b651796SEtienne Carriere if (res) { 1536*6b651796SEtienne Carriere EMSG("Failed to register clock provider: %#"PRIx32, res); 1537*6b651796SEtienne Carriere panic(); 1538*6b651796SEtienne Carriere } 1539*6b651796SEtienne Carriere 1540*6b651796SEtienne Carriere enable_static_secure_clocks(); 1541*6b651796SEtienne Carriere 1542*6b651796SEtienne Carriere return TEE_SUCCESS; 1543*6b651796SEtienne Carriere } 1544*6b651796SEtienne Carriere 1545*6b651796SEtienne Carriere static const struct dt_device_match stm32mp1_clock_match_table[] = { 1546*6b651796SEtienne Carriere { .compatible = "st,stm32mp1-rcc", .compat_data = &non_secure_rcc, }, 1547*6b651796SEtienne Carriere { .compatible = "st,stm32mp1-rcc-secure", }, 1548*6b651796SEtienne Carriere { } 1549*6b651796SEtienne Carriere }; 1550*6b651796SEtienne Carriere 1551*6b651796SEtienne Carriere DEFINE_DT_DRIVER(stm32mp1_clock_dt_driver) = { 1552*6b651796SEtienne Carriere .name = "stm32mp1_clock", 1553*6b651796SEtienne Carriere .type = DT_DRIVER_CLK, 1554*6b651796SEtienne Carriere .match_table = stm32mp1_clock_match_table, 1555*6b651796SEtienne Carriere .probe = stm32mp1_clock_provider_probe, 1556*6b651796SEtienne Carriere }; 1557*6b651796SEtienne Carriere #else /*CFG_DRIVERS_CLK_DT*/ 1558*6b651796SEtienne Carriere static TEE_Result stm32mp1_clk_early_init(void) 1559*6b651796SEtienne Carriere { 1560*6b651796SEtienne Carriere TEE_Result __maybe_unused res = TEE_ERROR_GENERIC; 1561*6b651796SEtienne Carriere 1562*6b651796SEtienne Carriere res = register_stm32mp1_clocks(); 1563*6b651796SEtienne Carriere if (res) { 1564*6b651796SEtienne Carriere EMSG("Failed to register clocks: %#"PRIx32, res); 1565*6b651796SEtienne Carriere panic(); 1566*6b651796SEtienne Carriere } 1567*6b651796SEtienne Carriere 1568*6b651796SEtienne Carriere enable_static_secure_clocks(); 1569*6b651796SEtienne Carriere 1570*6b651796SEtienne Carriere return TEE_SUCCESS; 1571*6b651796SEtienne Carriere } 1572*6b651796SEtienne Carriere 1573*6b651796SEtienne Carriere service_init(stm32mp1_clk_early_init); 1574*6b651796SEtienne Carriere #endif /*CFG_DRIVERS_CLK_DT*/ 1575