1*9be88e75SGabriel Fernandez /* 2*9be88e75SGabriel Fernandez * Copyright (C) 2022, STMicroelectronics - All Rights Reserved 3*9be88e75SGabriel Fernandez * 4*9be88e75SGabriel Fernandez * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause 5*9be88e75SGabriel Fernandez */ 6*9be88e75SGabriel Fernandez 7*9be88e75SGabriel Fernandez #include <assert.h> 8*9be88e75SGabriel Fernandez #include <errno.h> 9*9be88e75SGabriel Fernandez 10*9be88e75SGabriel Fernandez #include "clk-stm32-core.h" 11*9be88e75SGabriel Fernandez #include <common/debug.h> 12*9be88e75SGabriel Fernandez #include <common/fdt_wrappers.h> 13*9be88e75SGabriel Fernandez #include <drivers/clk.h> 14*9be88e75SGabriel Fernandez #include <drivers/delay_timer.h> 15*9be88e75SGabriel Fernandez #include <drivers/st/stm32mp_clkfunc.h> 16*9be88e75SGabriel Fernandez #include <lib/mmio.h> 17*9be88e75SGabriel Fernandez #include <lib/spinlock.h> 18*9be88e75SGabriel Fernandez 19*9be88e75SGabriel Fernandez static struct spinlock reg_lock; 20*9be88e75SGabriel Fernandez static struct spinlock refcount_lock; 21*9be88e75SGabriel Fernandez 22*9be88e75SGabriel Fernandez static struct stm32_clk_priv *stm32_clock_data; 23*9be88e75SGabriel Fernandez 24*9be88e75SGabriel Fernandez const struct stm32_clk_ops clk_mux_ops; 25*9be88e75SGabriel Fernandez 26*9be88e75SGabriel Fernandez struct stm32_clk_priv *clk_stm32_get_priv(void) 27*9be88e75SGabriel Fernandez { 28*9be88e75SGabriel Fernandez return stm32_clock_data; 29*9be88e75SGabriel Fernandez } 30*9be88e75SGabriel Fernandez 31*9be88e75SGabriel Fernandez static void stm32mp1_clk_lock(struct spinlock *lock) 32*9be88e75SGabriel Fernandez { 33*9be88e75SGabriel Fernandez if (stm32mp_lock_available()) { 34*9be88e75SGabriel Fernandez /* Assume interrupts are masked */ 35*9be88e75SGabriel Fernandez spin_lock(lock); 36*9be88e75SGabriel Fernandez } 37*9be88e75SGabriel Fernandez } 38*9be88e75SGabriel Fernandez 39*9be88e75SGabriel Fernandez static void stm32mp1_clk_unlock(struct spinlock *lock) 40*9be88e75SGabriel Fernandez { 41*9be88e75SGabriel Fernandez if (stm32mp_lock_available()) { 42*9be88e75SGabriel Fernandez spin_unlock(lock); 43*9be88e75SGabriel Fernandez } 44*9be88e75SGabriel Fernandez } 45*9be88e75SGabriel Fernandez 46*9be88e75SGabriel Fernandez void stm32mp1_clk_rcc_regs_lock(void) 47*9be88e75SGabriel Fernandez { 48*9be88e75SGabriel Fernandez stm32mp1_clk_lock(®_lock); 49*9be88e75SGabriel Fernandez } 50*9be88e75SGabriel Fernandez 51*9be88e75SGabriel Fernandez void stm32mp1_clk_rcc_regs_unlock(void) 52*9be88e75SGabriel Fernandez { 53*9be88e75SGabriel Fernandez stm32mp1_clk_unlock(®_lock); 54*9be88e75SGabriel Fernandez } 55*9be88e75SGabriel Fernandez 56*9be88e75SGabriel Fernandez #define TIMEOUT_US_1S U(1000000) 57*9be88e75SGabriel Fernandez #define OSCRDY_TIMEOUT TIMEOUT_US_1S 58*9be88e75SGabriel Fernandez 59*9be88e75SGabriel Fernandez struct clk_oscillator_data *clk_oscillator_get_data(struct stm32_clk_priv *priv, int id) 60*9be88e75SGabriel Fernandez { 61*9be88e75SGabriel Fernandez const struct clk_stm32 *clk = _clk_get(priv, id); 62*9be88e75SGabriel Fernandez struct stm32_osc_cfg *osc_cfg = clk->clock_cfg; 63*9be88e75SGabriel Fernandez int osc_id = osc_cfg->osc_id; 64*9be88e75SGabriel Fernandez 65*9be88e75SGabriel Fernandez return &priv->osci_data[osc_id]; 66*9be88e75SGabriel Fernandez } 67*9be88e75SGabriel Fernandez 68*9be88e75SGabriel Fernandez void clk_oscillator_set_bypass(struct stm32_clk_priv *priv, int id, bool digbyp, bool bypass) 69*9be88e75SGabriel Fernandez { 70*9be88e75SGabriel Fernandez struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); 71*9be88e75SGabriel Fernandez 72*9be88e75SGabriel Fernandez struct stm32_clk_bypass *bypass_data = osc_data->bypass; 73*9be88e75SGabriel Fernandez uintptr_t address; 74*9be88e75SGabriel Fernandez 75*9be88e75SGabriel Fernandez if (bypass_data == NULL) { 76*9be88e75SGabriel Fernandez return; 77*9be88e75SGabriel Fernandez } 78*9be88e75SGabriel Fernandez 79*9be88e75SGabriel Fernandez address = priv->base + bypass_data->offset; 80*9be88e75SGabriel Fernandez 81*9be88e75SGabriel Fernandez if (digbyp) { 82*9be88e75SGabriel Fernandez mmio_setbits_32(address, BIT(bypass_data->bit_digbyp)); 83*9be88e75SGabriel Fernandez } 84*9be88e75SGabriel Fernandez 85*9be88e75SGabriel Fernandez if (bypass || digbyp) { 86*9be88e75SGabriel Fernandez mmio_setbits_32(address, BIT(bypass_data->bit_byp)); 87*9be88e75SGabriel Fernandez } 88*9be88e75SGabriel Fernandez } 89*9be88e75SGabriel Fernandez 90*9be88e75SGabriel Fernandez void clk_oscillator_set_css(struct stm32_clk_priv *priv, int id, bool css) 91*9be88e75SGabriel Fernandez { 92*9be88e75SGabriel Fernandez struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); 93*9be88e75SGabriel Fernandez 94*9be88e75SGabriel Fernandez struct stm32_clk_css *css_data = osc_data->css; 95*9be88e75SGabriel Fernandez uintptr_t address; 96*9be88e75SGabriel Fernandez 97*9be88e75SGabriel Fernandez if (css_data == NULL) { 98*9be88e75SGabriel Fernandez return; 99*9be88e75SGabriel Fernandez } 100*9be88e75SGabriel Fernandez 101*9be88e75SGabriel Fernandez address = priv->base + css_data->offset; 102*9be88e75SGabriel Fernandez 103*9be88e75SGabriel Fernandez if (css) { 104*9be88e75SGabriel Fernandez mmio_setbits_32(address, BIT(css_data->bit_css)); 105*9be88e75SGabriel Fernandez } 106*9be88e75SGabriel Fernandez } 107*9be88e75SGabriel Fernandez 108*9be88e75SGabriel Fernandez void clk_oscillator_set_drive(struct stm32_clk_priv *priv, int id, uint8_t lsedrv) 109*9be88e75SGabriel Fernandez { 110*9be88e75SGabriel Fernandez struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); 111*9be88e75SGabriel Fernandez 112*9be88e75SGabriel Fernandez struct stm32_clk_drive *drive_data = osc_data->drive; 113*9be88e75SGabriel Fernandez uintptr_t address; 114*9be88e75SGabriel Fernandez uint32_t mask; 115*9be88e75SGabriel Fernandez uint32_t value; 116*9be88e75SGabriel Fernandez 117*9be88e75SGabriel Fernandez if (drive_data == NULL) { 118*9be88e75SGabriel Fernandez return; 119*9be88e75SGabriel Fernandez } 120*9be88e75SGabriel Fernandez 121*9be88e75SGabriel Fernandez address = priv->base + drive_data->offset; 122*9be88e75SGabriel Fernandez 123*9be88e75SGabriel Fernandez mask = (BIT(drive_data->drv_width) - 1U) << drive_data->drv_shift; 124*9be88e75SGabriel Fernandez 125*9be88e75SGabriel Fernandez /* 126*9be88e75SGabriel Fernandez * Warning: not recommended to switch directly from "high drive" 127*9be88e75SGabriel Fernandez * to "medium low drive", and vice-versa. 128*9be88e75SGabriel Fernandez */ 129*9be88e75SGabriel Fernandez value = (mmio_read_32(address) & mask) >> drive_data->drv_shift; 130*9be88e75SGabriel Fernandez 131*9be88e75SGabriel Fernandez while (value != lsedrv) { 132*9be88e75SGabriel Fernandez if (value > lsedrv) { 133*9be88e75SGabriel Fernandez value--; 134*9be88e75SGabriel Fernandez } else { 135*9be88e75SGabriel Fernandez value++; 136*9be88e75SGabriel Fernandez } 137*9be88e75SGabriel Fernandez 138*9be88e75SGabriel Fernandez mmio_clrsetbits_32(address, mask, value << drive_data->drv_shift); 139*9be88e75SGabriel Fernandez } 140*9be88e75SGabriel Fernandez } 141*9be88e75SGabriel Fernandez 142*9be88e75SGabriel Fernandez int clk_oscillator_wait_ready(struct stm32_clk_priv *priv, int id, bool ready_on) 143*9be88e75SGabriel Fernandez { 144*9be88e75SGabriel Fernandez struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); 145*9be88e75SGabriel Fernandez 146*9be88e75SGabriel Fernandez return _clk_stm32_gate_wait_ready(priv, osc_data->gate_id, ready_on); 147*9be88e75SGabriel Fernandez } 148*9be88e75SGabriel Fernandez 149*9be88e75SGabriel Fernandez int clk_oscillator_wait_ready_on(struct stm32_clk_priv *priv, int id) 150*9be88e75SGabriel Fernandez { 151*9be88e75SGabriel Fernandez return clk_oscillator_wait_ready(priv, id, true); 152*9be88e75SGabriel Fernandez } 153*9be88e75SGabriel Fernandez 154*9be88e75SGabriel Fernandez int clk_oscillator_wait_ready_off(struct stm32_clk_priv *priv, int id) 155*9be88e75SGabriel Fernandez { 156*9be88e75SGabriel Fernandez return clk_oscillator_wait_ready(priv, id, false); 157*9be88e75SGabriel Fernandez } 158*9be88e75SGabriel Fernandez 159*9be88e75SGabriel Fernandez static int clk_gate_enable(struct stm32_clk_priv *priv, int id) 160*9be88e75SGabriel Fernandez { 161*9be88e75SGabriel Fernandez const struct clk_stm32 *clk = _clk_get(priv, id); 162*9be88e75SGabriel Fernandez struct clk_gate_cfg *cfg = clk->clock_cfg; 163*9be88e75SGabriel Fernandez 164*9be88e75SGabriel Fernandez mmio_setbits_32(priv->base + cfg->offset, BIT(cfg->bit_idx)); 165*9be88e75SGabriel Fernandez 166*9be88e75SGabriel Fernandez return 0; 167*9be88e75SGabriel Fernandez } 168*9be88e75SGabriel Fernandez 169*9be88e75SGabriel Fernandez static void clk_gate_disable(struct stm32_clk_priv *priv, int id) 170*9be88e75SGabriel Fernandez { 171*9be88e75SGabriel Fernandez const struct clk_stm32 *clk = _clk_get(priv, id); 172*9be88e75SGabriel Fernandez struct clk_gate_cfg *cfg = clk->clock_cfg; 173*9be88e75SGabriel Fernandez 174*9be88e75SGabriel Fernandez mmio_clrbits_32(priv->base + cfg->offset, BIT(cfg->bit_idx)); 175*9be88e75SGabriel Fernandez } 176*9be88e75SGabriel Fernandez 177*9be88e75SGabriel Fernandez static bool clk_gate_is_enabled(struct stm32_clk_priv *priv, int id) 178*9be88e75SGabriel Fernandez { 179*9be88e75SGabriel Fernandez const struct clk_stm32 *clk = _clk_get(priv, id); 180*9be88e75SGabriel Fernandez struct clk_gate_cfg *cfg = clk->clock_cfg; 181*9be88e75SGabriel Fernandez 182*9be88e75SGabriel Fernandez return ((mmio_read_32(priv->base + cfg->offset) & BIT(cfg->bit_idx)) != 0U); 183*9be88e75SGabriel Fernandez } 184*9be88e75SGabriel Fernandez 185*9be88e75SGabriel Fernandez const struct stm32_clk_ops clk_gate_ops = { 186*9be88e75SGabriel Fernandez .enable = clk_gate_enable, 187*9be88e75SGabriel Fernandez .disable = clk_gate_disable, 188*9be88e75SGabriel Fernandez .is_enabled = clk_gate_is_enabled, 189*9be88e75SGabriel Fernandez }; 190*9be88e75SGabriel Fernandez 191*9be88e75SGabriel Fernandez void _clk_stm32_gate_disable(struct stm32_clk_priv *priv, uint16_t gate_id) 192*9be88e75SGabriel Fernandez { 193*9be88e75SGabriel Fernandez const struct gate_cfg *gate = &priv->gates[gate_id]; 194*9be88e75SGabriel Fernandez uintptr_t addr = priv->base + gate->offset; 195*9be88e75SGabriel Fernandez 196*9be88e75SGabriel Fernandez if (gate->set_clr != 0U) { 197*9be88e75SGabriel Fernandez mmio_write_32(addr + RCC_MP_ENCLRR_OFFSET, BIT(gate->bit_idx)); 198*9be88e75SGabriel Fernandez } else { 199*9be88e75SGabriel Fernandez mmio_clrbits_32(addr, BIT(gate->bit_idx)); 200*9be88e75SGabriel Fernandez } 201*9be88e75SGabriel Fernandez } 202*9be88e75SGabriel Fernandez 203*9be88e75SGabriel Fernandez int _clk_stm32_gate_enable(struct stm32_clk_priv *priv, uint16_t gate_id) 204*9be88e75SGabriel Fernandez { 205*9be88e75SGabriel Fernandez const struct gate_cfg *gate = &priv->gates[gate_id]; 206*9be88e75SGabriel Fernandez uintptr_t addr = priv->base + gate->offset; 207*9be88e75SGabriel Fernandez 208*9be88e75SGabriel Fernandez if (gate->set_clr != 0U) { 209*9be88e75SGabriel Fernandez mmio_write_32(addr, BIT(gate->bit_idx)); 210*9be88e75SGabriel Fernandez 211*9be88e75SGabriel Fernandez } else { 212*9be88e75SGabriel Fernandez mmio_setbits_32(addr, BIT(gate->bit_idx)); 213*9be88e75SGabriel Fernandez } 214*9be88e75SGabriel Fernandez 215*9be88e75SGabriel Fernandez return 0; 216*9be88e75SGabriel Fernandez } 217*9be88e75SGabriel Fernandez 218*9be88e75SGabriel Fernandez const char *_clk_stm32_get_name(struct stm32_clk_priv *priv, int id) 219*9be88e75SGabriel Fernandez { 220*9be88e75SGabriel Fernandez return priv->clks[id].name; 221*9be88e75SGabriel Fernandez } 222*9be88e75SGabriel Fernandez 223*9be88e75SGabriel Fernandez const char *clk_stm32_get_name(struct stm32_clk_priv *priv, 224*9be88e75SGabriel Fernandez unsigned long binding_id) 225*9be88e75SGabriel Fernandez { 226*9be88e75SGabriel Fernandez int id; 227*9be88e75SGabriel Fernandez 228*9be88e75SGabriel Fernandez id = clk_get_index(priv, binding_id); 229*9be88e75SGabriel Fernandez if (id == -EINVAL) { 230*9be88e75SGabriel Fernandez return NULL; 231*9be88e75SGabriel Fernandez } 232*9be88e75SGabriel Fernandez 233*9be88e75SGabriel Fernandez return _clk_stm32_get_name(priv, id); 234*9be88e75SGabriel Fernandez } 235*9be88e75SGabriel Fernandez 236*9be88e75SGabriel Fernandez const struct clk_stm32 *_clk_get(struct stm32_clk_priv *priv, int id) 237*9be88e75SGabriel Fernandez { 238*9be88e75SGabriel Fernandez if ((unsigned int)id < priv->num) { 239*9be88e75SGabriel Fernandez return &priv->clks[id]; 240*9be88e75SGabriel Fernandez } 241*9be88e75SGabriel Fernandez 242*9be88e75SGabriel Fernandez return NULL; 243*9be88e75SGabriel Fernandez } 244*9be88e75SGabriel Fernandez 245*9be88e75SGabriel Fernandez #define clk_div_mask(_width) GENMASK(((_width) - 1U), 0U) 246*9be88e75SGabriel Fernandez 247*9be88e75SGabriel Fernandez static unsigned int _get_table_div(const struct clk_div_table *table, 248*9be88e75SGabriel Fernandez unsigned int val) 249*9be88e75SGabriel Fernandez { 250*9be88e75SGabriel Fernandez const struct clk_div_table *clkt; 251*9be88e75SGabriel Fernandez 252*9be88e75SGabriel Fernandez for (clkt = table; clkt->div; clkt++) { 253*9be88e75SGabriel Fernandez if (clkt->val == val) { 254*9be88e75SGabriel Fernandez return clkt->div; 255*9be88e75SGabriel Fernandez } 256*9be88e75SGabriel Fernandez } 257*9be88e75SGabriel Fernandez 258*9be88e75SGabriel Fernandez return 0; 259*9be88e75SGabriel Fernandez } 260*9be88e75SGabriel Fernandez 261*9be88e75SGabriel Fernandez static unsigned int _get_div(const struct clk_div_table *table, 262*9be88e75SGabriel Fernandez unsigned int val, unsigned long flags, 263*9be88e75SGabriel Fernandez uint8_t width) 264*9be88e75SGabriel Fernandez { 265*9be88e75SGabriel Fernandez if ((flags & CLK_DIVIDER_ONE_BASED) != 0UL) { 266*9be88e75SGabriel Fernandez return val; 267*9be88e75SGabriel Fernandez } 268*9be88e75SGabriel Fernandez 269*9be88e75SGabriel Fernandez if ((flags & CLK_DIVIDER_POWER_OF_TWO) != 0UL) { 270*9be88e75SGabriel Fernandez return BIT(val); 271*9be88e75SGabriel Fernandez } 272*9be88e75SGabriel Fernandez 273*9be88e75SGabriel Fernandez if ((flags & CLK_DIVIDER_MAX_AT_ZERO) != 0UL) { 274*9be88e75SGabriel Fernandez return (val != 0U) ? val : BIT(width); 275*9be88e75SGabriel Fernandez } 276*9be88e75SGabriel Fernandez 277*9be88e75SGabriel Fernandez if (table != NULL) { 278*9be88e75SGabriel Fernandez return _get_table_div(table, val); 279*9be88e75SGabriel Fernandez } 280*9be88e75SGabriel Fernandez 281*9be88e75SGabriel Fernandez return val + 1U; 282*9be88e75SGabriel Fernandez } 283*9be88e75SGabriel Fernandez 284*9be88e75SGabriel Fernandez #define TIMEOUT_US_200MS U(200000) 285*9be88e75SGabriel Fernandez #define CLKSRC_TIMEOUT TIMEOUT_US_200MS 286*9be88e75SGabriel Fernandez 287*9be88e75SGabriel Fernandez int clk_mux_set_parent(struct stm32_clk_priv *priv, uint16_t pid, uint8_t sel) 288*9be88e75SGabriel Fernandez { 289*9be88e75SGabriel Fernandez const struct parent_cfg *parents = &priv->parents[pid & MUX_PARENT_MASK]; 290*9be88e75SGabriel Fernandez const struct mux_cfg *mux = parents->mux; 291*9be88e75SGabriel Fernandez uintptr_t address = priv->base + mux->offset; 292*9be88e75SGabriel Fernandez uint32_t mask; 293*9be88e75SGabriel Fernandez uint64_t timeout; 294*9be88e75SGabriel Fernandez 295*9be88e75SGabriel Fernandez mask = MASK_WIDTH_SHIFT(mux->width, mux->shift); 296*9be88e75SGabriel Fernandez 297*9be88e75SGabriel Fernandez mmio_clrsetbits_32(address, mask, (sel << mux->shift) & mask); 298*9be88e75SGabriel Fernandez 299*9be88e75SGabriel Fernandez if (mux->bitrdy == MUX_NO_BIT_RDY) { 300*9be88e75SGabriel Fernandez return 0; 301*9be88e75SGabriel Fernandez } 302*9be88e75SGabriel Fernandez 303*9be88e75SGabriel Fernandez timeout = timeout_init_us(CLKSRC_TIMEOUT); 304*9be88e75SGabriel Fernandez 305*9be88e75SGabriel Fernandez mask = BIT(mux->bitrdy); 306*9be88e75SGabriel Fernandez 307*9be88e75SGabriel Fernandez while ((mmio_read_32(address) & mask) == 0U) { 308*9be88e75SGabriel Fernandez if (timeout_elapsed(timeout)) { 309*9be88e75SGabriel Fernandez return -ETIMEDOUT; 310*9be88e75SGabriel Fernandez } 311*9be88e75SGabriel Fernandez } 312*9be88e75SGabriel Fernandez 313*9be88e75SGabriel Fernandez return 0; 314*9be88e75SGabriel Fernandez } 315*9be88e75SGabriel Fernandez 316*9be88e75SGabriel Fernandez int _clk_stm32_set_parent(struct stm32_clk_priv *priv, int clk, int clkp) 317*9be88e75SGabriel Fernandez { 318*9be88e75SGabriel Fernandez const struct parent_cfg *parents; 319*9be88e75SGabriel Fernandez uint16_t pid; 320*9be88e75SGabriel Fernandez uint8_t sel; 321*9be88e75SGabriel Fernandez int old_parent; 322*9be88e75SGabriel Fernandez 323*9be88e75SGabriel Fernandez pid = priv->clks[clk].parent; 324*9be88e75SGabriel Fernandez 325*9be88e75SGabriel Fernandez if ((pid == CLK_IS_ROOT) || (pid < MUX_MAX_PARENTS)) { 326*9be88e75SGabriel Fernandez return -EINVAL; 327*9be88e75SGabriel Fernandez } 328*9be88e75SGabriel Fernandez 329*9be88e75SGabriel Fernandez old_parent = _clk_stm32_get_parent(priv, clk); 330*9be88e75SGabriel Fernandez if (old_parent == clkp) { 331*9be88e75SGabriel Fernandez return 0; 332*9be88e75SGabriel Fernandez } 333*9be88e75SGabriel Fernandez 334*9be88e75SGabriel Fernandez parents = &priv->parents[pid & MUX_PARENT_MASK]; 335*9be88e75SGabriel Fernandez 336*9be88e75SGabriel Fernandez for (sel = 0; sel < parents->num_parents; sel++) { 337*9be88e75SGabriel Fernandez if (parents->id_parents[sel] == (uint16_t)clkp) { 338*9be88e75SGabriel Fernandez bool clk_was_enabled = _clk_stm32_is_enabled(priv, clk); 339*9be88e75SGabriel Fernandez int err = 0; 340*9be88e75SGabriel Fernandez 341*9be88e75SGabriel Fernandez /* Enable the parents (for glitch free mux) */ 342*9be88e75SGabriel Fernandez _clk_stm32_enable(priv, clkp); 343*9be88e75SGabriel Fernandez _clk_stm32_enable(priv, old_parent); 344*9be88e75SGabriel Fernandez 345*9be88e75SGabriel Fernandez err = clk_mux_set_parent(priv, pid, sel); 346*9be88e75SGabriel Fernandez 347*9be88e75SGabriel Fernandez _clk_stm32_disable(priv, old_parent); 348*9be88e75SGabriel Fernandez 349*9be88e75SGabriel Fernandez if (clk_was_enabled) { 350*9be88e75SGabriel Fernandez _clk_stm32_disable(priv, old_parent); 351*9be88e75SGabriel Fernandez } else { 352*9be88e75SGabriel Fernandez _clk_stm32_disable(priv, clkp); 353*9be88e75SGabriel Fernandez } 354*9be88e75SGabriel Fernandez 355*9be88e75SGabriel Fernandez return err; 356*9be88e75SGabriel Fernandez } 357*9be88e75SGabriel Fernandez } 358*9be88e75SGabriel Fernandez 359*9be88e75SGabriel Fernandez return -EINVAL; 360*9be88e75SGabriel Fernandez } 361*9be88e75SGabriel Fernandez 362*9be88e75SGabriel Fernandez int clk_mux_get_parent(struct stm32_clk_priv *priv, uint32_t mux_id) 363*9be88e75SGabriel Fernandez { 364*9be88e75SGabriel Fernandez const struct parent_cfg *parent; 365*9be88e75SGabriel Fernandez const struct mux_cfg *mux; 366*9be88e75SGabriel Fernandez uint32_t mask; 367*9be88e75SGabriel Fernandez 368*9be88e75SGabriel Fernandez if (mux_id >= priv->nb_parents) { 369*9be88e75SGabriel Fernandez panic(); 370*9be88e75SGabriel Fernandez } 371*9be88e75SGabriel Fernandez 372*9be88e75SGabriel Fernandez parent = &priv->parents[mux_id]; 373*9be88e75SGabriel Fernandez mux = parent->mux; 374*9be88e75SGabriel Fernandez 375*9be88e75SGabriel Fernandez mask = MASK_WIDTH_SHIFT(mux->width, mux->shift); 376*9be88e75SGabriel Fernandez 377*9be88e75SGabriel Fernandez return (mmio_read_32(priv->base + mux->offset) & mask) >> mux->shift; 378*9be88e75SGabriel Fernandez } 379*9be88e75SGabriel Fernandez 380*9be88e75SGabriel Fernandez int _clk_stm32_set_parent_by_index(struct stm32_clk_priv *priv, int clk, int sel) 381*9be88e75SGabriel Fernandez { 382*9be88e75SGabriel Fernandez uint16_t pid; 383*9be88e75SGabriel Fernandez 384*9be88e75SGabriel Fernandez pid = priv->clks[clk].parent; 385*9be88e75SGabriel Fernandez 386*9be88e75SGabriel Fernandez if ((pid == CLK_IS_ROOT) || (pid < MUX_MAX_PARENTS)) { 387*9be88e75SGabriel Fernandez return -EINVAL; 388*9be88e75SGabriel Fernandez } 389*9be88e75SGabriel Fernandez 390*9be88e75SGabriel Fernandez return clk_mux_set_parent(priv, pid, sel); 391*9be88e75SGabriel Fernandez } 392*9be88e75SGabriel Fernandez 393*9be88e75SGabriel Fernandez int _clk_stm32_get_parent(struct stm32_clk_priv *priv, int clk_id) 394*9be88e75SGabriel Fernandez { 395*9be88e75SGabriel Fernandez const struct clk_stm32 *clk = _clk_get(priv, clk_id); 396*9be88e75SGabriel Fernandez const struct parent_cfg *parent; 397*9be88e75SGabriel Fernandez uint16_t mux_id; 398*9be88e75SGabriel Fernandez int sel; 399*9be88e75SGabriel Fernandez 400*9be88e75SGabriel Fernandez mux_id = priv->clks[clk_id].parent; 401*9be88e75SGabriel Fernandez if (mux_id == CLK_IS_ROOT) { 402*9be88e75SGabriel Fernandez return CLK_IS_ROOT; 403*9be88e75SGabriel Fernandez } 404*9be88e75SGabriel Fernandez 405*9be88e75SGabriel Fernandez if (mux_id < MUX_MAX_PARENTS) { 406*9be88e75SGabriel Fernandez return mux_id & MUX_PARENT_MASK; 407*9be88e75SGabriel Fernandez } 408*9be88e75SGabriel Fernandez 409*9be88e75SGabriel Fernandez mux_id &= MUX_PARENT_MASK; 410*9be88e75SGabriel Fernandez parent = &priv->parents[mux_id]; 411*9be88e75SGabriel Fernandez 412*9be88e75SGabriel Fernandez if (clk->ops->get_parent != NULL) { 413*9be88e75SGabriel Fernandez sel = clk->ops->get_parent(priv, clk_id); 414*9be88e75SGabriel Fernandez } else { 415*9be88e75SGabriel Fernandez sel = clk_mux_get_parent(priv, mux_id); 416*9be88e75SGabriel Fernandez } 417*9be88e75SGabriel Fernandez 418*9be88e75SGabriel Fernandez if (sel < parent->num_parents) { 419*9be88e75SGabriel Fernandez return parent->id_parents[sel]; 420*9be88e75SGabriel Fernandez } 421*9be88e75SGabriel Fernandez 422*9be88e75SGabriel Fernandez return -EINVAL; 423*9be88e75SGabriel Fernandez } 424*9be88e75SGabriel Fernandez 425*9be88e75SGabriel Fernandez int _clk_stm32_get_parent_index(struct stm32_clk_priv *priv, int clk_id) 426*9be88e75SGabriel Fernandez { 427*9be88e75SGabriel Fernandez uint16_t mux_id; 428*9be88e75SGabriel Fernandez 429*9be88e75SGabriel Fernandez mux_id = priv->clks[clk_id].parent; 430*9be88e75SGabriel Fernandez if (mux_id == CLK_IS_ROOT) { 431*9be88e75SGabriel Fernandez return CLK_IS_ROOT; 432*9be88e75SGabriel Fernandez } 433*9be88e75SGabriel Fernandez 434*9be88e75SGabriel Fernandez if (mux_id < MUX_MAX_PARENTS) { 435*9be88e75SGabriel Fernandez return mux_id & MUX_PARENT_MASK; 436*9be88e75SGabriel Fernandez } 437*9be88e75SGabriel Fernandez 438*9be88e75SGabriel Fernandez mux_id &= MUX_PARENT_MASK; 439*9be88e75SGabriel Fernandez 440*9be88e75SGabriel Fernandez return clk_mux_get_parent(priv, mux_id); 441*9be88e75SGabriel Fernandez } 442*9be88e75SGabriel Fernandez 443*9be88e75SGabriel Fernandez int _clk_stm32_get_parent_by_index(struct stm32_clk_priv *priv, int clk_id, int idx) 444*9be88e75SGabriel Fernandez { 445*9be88e75SGabriel Fernandez const struct parent_cfg *parent; 446*9be88e75SGabriel Fernandez uint16_t mux_id; 447*9be88e75SGabriel Fernandez 448*9be88e75SGabriel Fernandez mux_id = priv->clks[clk_id].parent; 449*9be88e75SGabriel Fernandez if (mux_id == CLK_IS_ROOT) { 450*9be88e75SGabriel Fernandez return CLK_IS_ROOT; 451*9be88e75SGabriel Fernandez } 452*9be88e75SGabriel Fernandez 453*9be88e75SGabriel Fernandez if (mux_id < MUX_MAX_PARENTS) { 454*9be88e75SGabriel Fernandez return mux_id & MUX_PARENT_MASK; 455*9be88e75SGabriel Fernandez } 456*9be88e75SGabriel Fernandez 457*9be88e75SGabriel Fernandez mux_id &= MUX_PARENT_MASK; 458*9be88e75SGabriel Fernandez parent = &priv->parents[mux_id]; 459*9be88e75SGabriel Fernandez 460*9be88e75SGabriel Fernandez if (idx < parent->num_parents) { 461*9be88e75SGabriel Fernandez return parent->id_parents[idx]; 462*9be88e75SGabriel Fernandez } 463*9be88e75SGabriel Fernandez 464*9be88e75SGabriel Fernandez return -EINVAL; 465*9be88e75SGabriel Fernandez } 466*9be88e75SGabriel Fernandez 467*9be88e75SGabriel Fernandez int clk_get_index(struct stm32_clk_priv *priv, unsigned long binding_id) 468*9be88e75SGabriel Fernandez { 469*9be88e75SGabriel Fernandez unsigned int i; 470*9be88e75SGabriel Fernandez 471*9be88e75SGabriel Fernandez for (i = 0U; i < priv->num; i++) { 472*9be88e75SGabriel Fernandez if (binding_id == priv->clks[i].binding) { 473*9be88e75SGabriel Fernandez return (int)i; 474*9be88e75SGabriel Fernandez } 475*9be88e75SGabriel Fernandez } 476*9be88e75SGabriel Fernandez 477*9be88e75SGabriel Fernandez return -EINVAL; 478*9be88e75SGabriel Fernandez } 479*9be88e75SGabriel Fernandez 480*9be88e75SGabriel Fernandez unsigned long _clk_stm32_get_rate(struct stm32_clk_priv *priv, int id) 481*9be88e75SGabriel Fernandez { 482*9be88e75SGabriel Fernandez const struct clk_stm32 *clk = _clk_get(priv, id); 483*9be88e75SGabriel Fernandez int parent; 484*9be88e75SGabriel Fernandez unsigned long rate = 0UL; 485*9be88e75SGabriel Fernandez 486*9be88e75SGabriel Fernandez if ((unsigned int)id >= priv->num) { 487*9be88e75SGabriel Fernandez return rate; 488*9be88e75SGabriel Fernandez } 489*9be88e75SGabriel Fernandez 490*9be88e75SGabriel Fernandez parent = _clk_stm32_get_parent(priv, id); 491*9be88e75SGabriel Fernandez 492*9be88e75SGabriel Fernandez if (clk->ops->recalc_rate != NULL) { 493*9be88e75SGabriel Fernandez unsigned long prate = 0UL; 494*9be88e75SGabriel Fernandez 495*9be88e75SGabriel Fernandez if (parent != CLK_IS_ROOT) { 496*9be88e75SGabriel Fernandez prate = _clk_stm32_get_rate(priv, parent); 497*9be88e75SGabriel Fernandez } 498*9be88e75SGabriel Fernandez 499*9be88e75SGabriel Fernandez rate = clk->ops->recalc_rate(priv, id, prate); 500*9be88e75SGabriel Fernandez 501*9be88e75SGabriel Fernandez return rate; 502*9be88e75SGabriel Fernandez } 503*9be88e75SGabriel Fernandez 504*9be88e75SGabriel Fernandez switch (parent) { 505*9be88e75SGabriel Fernandez case CLK_IS_ROOT: 506*9be88e75SGabriel Fernandez panic(); 507*9be88e75SGabriel Fernandez 508*9be88e75SGabriel Fernandez default: 509*9be88e75SGabriel Fernandez rate = _clk_stm32_get_rate(priv, parent); 510*9be88e75SGabriel Fernandez break; 511*9be88e75SGabriel Fernandez } 512*9be88e75SGabriel Fernandez return rate; 513*9be88e75SGabriel Fernandez 514*9be88e75SGabriel Fernandez } 515*9be88e75SGabriel Fernandez 516*9be88e75SGabriel Fernandez unsigned long _clk_stm32_get_parent_rate(struct stm32_clk_priv *priv, int id) 517*9be88e75SGabriel Fernandez { 518*9be88e75SGabriel Fernandez int parent_id = _clk_stm32_get_parent(priv, id); 519*9be88e75SGabriel Fernandez 520*9be88e75SGabriel Fernandez return _clk_stm32_get_rate(priv, parent_id); 521*9be88e75SGabriel Fernandez } 522*9be88e75SGabriel Fernandez 523*9be88e75SGabriel Fernandez static uint8_t _stm32_clk_get_flags(struct stm32_clk_priv *priv, int id) 524*9be88e75SGabriel Fernandez { 525*9be88e75SGabriel Fernandez return priv->clks[id].flags; 526*9be88e75SGabriel Fernandez } 527*9be88e75SGabriel Fernandez 528*9be88e75SGabriel Fernandez bool _stm32_clk_is_flags(struct stm32_clk_priv *priv, int id, uint8_t flag) 529*9be88e75SGabriel Fernandez { 530*9be88e75SGabriel Fernandez if (_stm32_clk_get_flags(priv, id) & flag) { 531*9be88e75SGabriel Fernandez return true; 532*9be88e75SGabriel Fernandez } 533*9be88e75SGabriel Fernandez 534*9be88e75SGabriel Fernandez return false; 535*9be88e75SGabriel Fernandez } 536*9be88e75SGabriel Fernandez 537*9be88e75SGabriel Fernandez int clk_stm32_enable_call_ops(struct stm32_clk_priv *priv, uint16_t id) 538*9be88e75SGabriel Fernandez { 539*9be88e75SGabriel Fernandez const struct clk_stm32 *clk = _clk_get(priv, id); 540*9be88e75SGabriel Fernandez 541*9be88e75SGabriel Fernandez if (clk->ops->enable != NULL) { 542*9be88e75SGabriel Fernandez clk->ops->enable(priv, id); 543*9be88e75SGabriel Fernandez } 544*9be88e75SGabriel Fernandez 545*9be88e75SGabriel Fernandez return 0; 546*9be88e75SGabriel Fernandez } 547*9be88e75SGabriel Fernandez 548*9be88e75SGabriel Fernandez static int _clk_stm32_enable_core(struct stm32_clk_priv *priv, int id) 549*9be88e75SGabriel Fernandez { 550*9be88e75SGabriel Fernandez int parent; 551*9be88e75SGabriel Fernandez int ret = 0; 552*9be88e75SGabriel Fernandez 553*9be88e75SGabriel Fernandez if (priv->gate_refcounts[id] == 0U) { 554*9be88e75SGabriel Fernandez parent = _clk_stm32_get_parent(priv, id); 555*9be88e75SGabriel Fernandez if (parent != CLK_IS_ROOT) { 556*9be88e75SGabriel Fernandez ret = _clk_stm32_enable_core(priv, parent); 557*9be88e75SGabriel Fernandez if (ret) { 558*9be88e75SGabriel Fernandez return ret; 559*9be88e75SGabriel Fernandez } 560*9be88e75SGabriel Fernandez } 561*9be88e75SGabriel Fernandez clk_stm32_enable_call_ops(priv, id); 562*9be88e75SGabriel Fernandez } 563*9be88e75SGabriel Fernandez 564*9be88e75SGabriel Fernandez priv->gate_refcounts[id]++; 565*9be88e75SGabriel Fernandez 566*9be88e75SGabriel Fernandez if (priv->gate_refcounts[id] == UINT_MAX) { 567*9be88e75SGabriel Fernandez ERROR("%s: %d max enable count !", __func__, id); 568*9be88e75SGabriel Fernandez panic(); 569*9be88e75SGabriel Fernandez } 570*9be88e75SGabriel Fernandez 571*9be88e75SGabriel Fernandez return 0; 572*9be88e75SGabriel Fernandez } 573*9be88e75SGabriel Fernandez 574*9be88e75SGabriel Fernandez int _clk_stm32_enable(struct stm32_clk_priv *priv, int id) 575*9be88e75SGabriel Fernandez { 576*9be88e75SGabriel Fernandez int ret; 577*9be88e75SGabriel Fernandez 578*9be88e75SGabriel Fernandez stm32mp1_clk_lock(&refcount_lock); 579*9be88e75SGabriel Fernandez ret = _clk_stm32_enable_core(priv, id); 580*9be88e75SGabriel Fernandez stm32mp1_clk_unlock(&refcount_lock); 581*9be88e75SGabriel Fernandez 582*9be88e75SGabriel Fernandez return ret; 583*9be88e75SGabriel Fernandez } 584*9be88e75SGabriel Fernandez 585*9be88e75SGabriel Fernandez void clk_stm32_disable_call_ops(struct stm32_clk_priv *priv, uint16_t id) 586*9be88e75SGabriel Fernandez { 587*9be88e75SGabriel Fernandez const struct clk_stm32 *clk = _clk_get(priv, id); 588*9be88e75SGabriel Fernandez 589*9be88e75SGabriel Fernandez if (clk->ops->disable != NULL) { 590*9be88e75SGabriel Fernandez clk->ops->disable(priv, id); 591*9be88e75SGabriel Fernandez } 592*9be88e75SGabriel Fernandez } 593*9be88e75SGabriel Fernandez 594*9be88e75SGabriel Fernandez static void _clk_stm32_disable_core(struct stm32_clk_priv *priv, int id) 595*9be88e75SGabriel Fernandez { 596*9be88e75SGabriel Fernandez int parent; 597*9be88e75SGabriel Fernandez 598*9be88e75SGabriel Fernandez if ((priv->gate_refcounts[id] == 1U) && _stm32_clk_is_flags(priv, id, CLK_IS_CRITICAL)) { 599*9be88e75SGabriel Fernandez return; 600*9be88e75SGabriel Fernandez } 601*9be88e75SGabriel Fernandez 602*9be88e75SGabriel Fernandez if (priv->gate_refcounts[id] == 0U) { 603*9be88e75SGabriel Fernandez /* case of clock ignore unused */ 604*9be88e75SGabriel Fernandez if (_clk_stm32_is_enabled(priv, id)) { 605*9be88e75SGabriel Fernandez clk_stm32_disable_call_ops(priv, id); 606*9be88e75SGabriel Fernandez return; 607*9be88e75SGabriel Fernandez } 608*9be88e75SGabriel Fernandez VERBOSE("%s: %d already disabled !\n\n", __func__, id); 609*9be88e75SGabriel Fernandez return; 610*9be88e75SGabriel Fernandez } 611*9be88e75SGabriel Fernandez 612*9be88e75SGabriel Fernandez if (--priv->gate_refcounts[id] > 0U) { 613*9be88e75SGabriel Fernandez return; 614*9be88e75SGabriel Fernandez } 615*9be88e75SGabriel Fernandez 616*9be88e75SGabriel Fernandez clk_stm32_disable_call_ops(priv, id); 617*9be88e75SGabriel Fernandez 618*9be88e75SGabriel Fernandez parent = _clk_stm32_get_parent(priv, id); 619*9be88e75SGabriel Fernandez if (parent != CLK_IS_ROOT) { 620*9be88e75SGabriel Fernandez _clk_stm32_disable_core(priv, parent); 621*9be88e75SGabriel Fernandez } 622*9be88e75SGabriel Fernandez } 623*9be88e75SGabriel Fernandez 624*9be88e75SGabriel Fernandez void _clk_stm32_disable(struct stm32_clk_priv *priv, int id) 625*9be88e75SGabriel Fernandez { 626*9be88e75SGabriel Fernandez stm32mp1_clk_lock(&refcount_lock); 627*9be88e75SGabriel Fernandez 628*9be88e75SGabriel Fernandez _clk_stm32_disable_core(priv, id); 629*9be88e75SGabriel Fernandez 630*9be88e75SGabriel Fernandez stm32mp1_clk_unlock(&refcount_lock); 631*9be88e75SGabriel Fernandez } 632*9be88e75SGabriel Fernandez 633*9be88e75SGabriel Fernandez bool _clk_stm32_is_enabled(struct stm32_clk_priv *priv, int id) 634*9be88e75SGabriel Fernandez { 635*9be88e75SGabriel Fernandez const struct clk_stm32 *clk = _clk_get(priv, id); 636*9be88e75SGabriel Fernandez 637*9be88e75SGabriel Fernandez if (clk->ops->is_enabled != NULL) { 638*9be88e75SGabriel Fernandez return clk->ops->is_enabled(priv, id); 639*9be88e75SGabriel Fernandez } 640*9be88e75SGabriel Fernandez 641*9be88e75SGabriel Fernandez return priv->gate_refcounts[id]; 642*9be88e75SGabriel Fernandez } 643*9be88e75SGabriel Fernandez 644*9be88e75SGabriel Fernandez static int clk_stm32_enable(unsigned long binding_id) 645*9be88e75SGabriel Fernandez { 646*9be88e75SGabriel Fernandez struct stm32_clk_priv *priv = clk_stm32_get_priv(); 647*9be88e75SGabriel Fernandez int id; 648*9be88e75SGabriel Fernandez 649*9be88e75SGabriel Fernandez id = clk_get_index(priv, binding_id); 650*9be88e75SGabriel Fernandez if (id == -EINVAL) { 651*9be88e75SGabriel Fernandez return id; 652*9be88e75SGabriel Fernandez } 653*9be88e75SGabriel Fernandez 654*9be88e75SGabriel Fernandez return _clk_stm32_enable(priv, id); 655*9be88e75SGabriel Fernandez } 656*9be88e75SGabriel Fernandez 657*9be88e75SGabriel Fernandez static void clk_stm32_disable(unsigned long binding_id) 658*9be88e75SGabriel Fernandez { 659*9be88e75SGabriel Fernandez struct stm32_clk_priv *priv = clk_stm32_get_priv(); 660*9be88e75SGabriel Fernandez int id; 661*9be88e75SGabriel Fernandez 662*9be88e75SGabriel Fernandez id = clk_get_index(priv, binding_id); 663*9be88e75SGabriel Fernandez if (id != -EINVAL) { 664*9be88e75SGabriel Fernandez _clk_stm32_disable(priv, id); 665*9be88e75SGabriel Fernandez } 666*9be88e75SGabriel Fernandez } 667*9be88e75SGabriel Fernandez 668*9be88e75SGabriel Fernandez static bool clk_stm32_is_enabled(unsigned long binding_id) 669*9be88e75SGabriel Fernandez { 670*9be88e75SGabriel Fernandez struct stm32_clk_priv *priv = clk_stm32_get_priv(); 671*9be88e75SGabriel Fernandez int id; 672*9be88e75SGabriel Fernandez 673*9be88e75SGabriel Fernandez id = clk_get_index(priv, binding_id); 674*9be88e75SGabriel Fernandez if (id == -EINVAL) { 675*9be88e75SGabriel Fernandez return false; 676*9be88e75SGabriel Fernandez } 677*9be88e75SGabriel Fernandez 678*9be88e75SGabriel Fernandez return _clk_stm32_is_enabled(priv, id); 679*9be88e75SGabriel Fernandez } 680*9be88e75SGabriel Fernandez 681*9be88e75SGabriel Fernandez static unsigned long clk_stm32_get_rate(unsigned long binding_id) 682*9be88e75SGabriel Fernandez { 683*9be88e75SGabriel Fernandez struct stm32_clk_priv *priv = clk_stm32_get_priv(); 684*9be88e75SGabriel Fernandez int id; 685*9be88e75SGabriel Fernandez 686*9be88e75SGabriel Fernandez id = clk_get_index(priv, binding_id); 687*9be88e75SGabriel Fernandez if (id == -EINVAL) { 688*9be88e75SGabriel Fernandez return 0UL; 689*9be88e75SGabriel Fernandez } 690*9be88e75SGabriel Fernandez 691*9be88e75SGabriel Fernandez return _clk_stm32_get_rate(priv, id); 692*9be88e75SGabriel Fernandez } 693*9be88e75SGabriel Fernandez 694*9be88e75SGabriel Fernandez static int clk_stm32_get_parent(unsigned long binding_id) 695*9be88e75SGabriel Fernandez { 696*9be88e75SGabriel Fernandez struct stm32_clk_priv *priv = clk_stm32_get_priv(); 697*9be88e75SGabriel Fernandez int id; 698*9be88e75SGabriel Fernandez 699*9be88e75SGabriel Fernandez id = clk_get_index(priv, binding_id); 700*9be88e75SGabriel Fernandez if (id == -EINVAL) { 701*9be88e75SGabriel Fernandez return id; 702*9be88e75SGabriel Fernandez } 703*9be88e75SGabriel Fernandez 704*9be88e75SGabriel Fernandez return _clk_stm32_get_parent(priv, id); 705*9be88e75SGabriel Fernandez } 706*9be88e75SGabriel Fernandez 707*9be88e75SGabriel Fernandez static const struct clk_ops stm32mp_clk_ops = { 708*9be88e75SGabriel Fernandez .enable = clk_stm32_enable, 709*9be88e75SGabriel Fernandez .disable = clk_stm32_disable, 710*9be88e75SGabriel Fernandez .is_enabled = clk_stm32_is_enabled, 711*9be88e75SGabriel Fernandez .get_rate = clk_stm32_get_rate, 712*9be88e75SGabriel Fernandez .get_parent = clk_stm32_get_parent, 713*9be88e75SGabriel Fernandez }; 714*9be88e75SGabriel Fernandez 715*9be88e75SGabriel Fernandez void clk_stm32_enable_critical_clocks(void) 716*9be88e75SGabriel Fernandez { 717*9be88e75SGabriel Fernandez struct stm32_clk_priv *priv = clk_stm32_get_priv(); 718*9be88e75SGabriel Fernandez unsigned int i; 719*9be88e75SGabriel Fernandez 720*9be88e75SGabriel Fernandez for (i = 0U; i < priv->num; i++) { 721*9be88e75SGabriel Fernandez if (_stm32_clk_is_flags(priv, i, CLK_IS_CRITICAL)) { 722*9be88e75SGabriel Fernandez _clk_stm32_enable(priv, i); 723*9be88e75SGabriel Fernandez } 724*9be88e75SGabriel Fernandez } 725*9be88e75SGabriel Fernandez } 726*9be88e75SGabriel Fernandez 727*9be88e75SGabriel Fernandez static void stm32_clk_register(void) 728*9be88e75SGabriel Fernandez { 729*9be88e75SGabriel Fernandez clk_register(&stm32mp_clk_ops); 730*9be88e75SGabriel Fernandez } 731*9be88e75SGabriel Fernandez 732*9be88e75SGabriel Fernandez uint32_t clk_stm32_div_get_value(struct stm32_clk_priv *priv, int div_id) 733*9be88e75SGabriel Fernandez { 734*9be88e75SGabriel Fernandez const struct div_cfg *divider = &priv->div[div_id]; 735*9be88e75SGabriel Fernandez uint32_t val = 0; 736*9be88e75SGabriel Fernandez 737*9be88e75SGabriel Fernandez val = mmio_read_32(priv->base + divider->offset) >> divider->shift; 738*9be88e75SGabriel Fernandez val &= clk_div_mask(divider->width); 739*9be88e75SGabriel Fernandez 740*9be88e75SGabriel Fernandez return val; 741*9be88e75SGabriel Fernandez } 742*9be88e75SGabriel Fernandez 743*9be88e75SGabriel Fernandez unsigned long _clk_stm32_divider_recalc(struct stm32_clk_priv *priv, 744*9be88e75SGabriel Fernandez int div_id, 745*9be88e75SGabriel Fernandez unsigned long prate) 746*9be88e75SGabriel Fernandez { 747*9be88e75SGabriel Fernandez const struct div_cfg *divider = &priv->div[div_id]; 748*9be88e75SGabriel Fernandez uint32_t val = clk_stm32_div_get_value(priv, div_id); 749*9be88e75SGabriel Fernandez unsigned int div = 0U; 750*9be88e75SGabriel Fernandez 751*9be88e75SGabriel Fernandez div = _get_div(divider->table, val, divider->flags, divider->width); 752*9be88e75SGabriel Fernandez if (div == 0U) { 753*9be88e75SGabriel Fernandez return prate; 754*9be88e75SGabriel Fernandez } 755*9be88e75SGabriel Fernandez 756*9be88e75SGabriel Fernandez return div_round_up((uint64_t)prate, div); 757*9be88e75SGabriel Fernandez } 758*9be88e75SGabriel Fernandez 759*9be88e75SGabriel Fernandez unsigned long clk_stm32_divider_recalc(struct stm32_clk_priv *priv, int id, 760*9be88e75SGabriel Fernandez unsigned long prate) 761*9be88e75SGabriel Fernandez { 762*9be88e75SGabriel Fernandez const struct clk_stm32 *clk = _clk_get(priv, id); 763*9be88e75SGabriel Fernandez struct clk_stm32_div_cfg *div_cfg = clk->clock_cfg; 764*9be88e75SGabriel Fernandez 765*9be88e75SGabriel Fernandez return _clk_stm32_divider_recalc(priv, div_cfg->id, prate); 766*9be88e75SGabriel Fernandez } 767*9be88e75SGabriel Fernandez 768*9be88e75SGabriel Fernandez const struct stm32_clk_ops clk_stm32_divider_ops = { 769*9be88e75SGabriel Fernandez .recalc_rate = clk_stm32_divider_recalc, 770*9be88e75SGabriel Fernandez }; 771*9be88e75SGabriel Fernandez 772*9be88e75SGabriel Fernandez int clk_stm32_set_div(struct stm32_clk_priv *priv, uint32_t div_id, uint32_t value) 773*9be88e75SGabriel Fernandez { 774*9be88e75SGabriel Fernandez const struct div_cfg *divider; 775*9be88e75SGabriel Fernandez uintptr_t address; 776*9be88e75SGabriel Fernandez uint64_t timeout; 777*9be88e75SGabriel Fernandez uint32_t mask; 778*9be88e75SGabriel Fernandez 779*9be88e75SGabriel Fernandez if (div_id >= priv->nb_div) { 780*9be88e75SGabriel Fernandez panic(); 781*9be88e75SGabriel Fernandez } 782*9be88e75SGabriel Fernandez 783*9be88e75SGabriel Fernandez divider = &priv->div[div_id]; 784*9be88e75SGabriel Fernandez address = priv->base + divider->offset; 785*9be88e75SGabriel Fernandez 786*9be88e75SGabriel Fernandez mask = MASK_WIDTH_SHIFT(divider->width, divider->shift); 787*9be88e75SGabriel Fernandez mmio_clrsetbits_32(address, mask, (value << divider->shift) & mask); 788*9be88e75SGabriel Fernandez 789*9be88e75SGabriel Fernandez if (divider->bitrdy == DIV_NO_BIT_RDY) { 790*9be88e75SGabriel Fernandez return 0; 791*9be88e75SGabriel Fernandez } 792*9be88e75SGabriel Fernandez 793*9be88e75SGabriel Fernandez timeout = timeout_init_us(CLKSRC_TIMEOUT); 794*9be88e75SGabriel Fernandez mask = BIT(divider->bitrdy); 795*9be88e75SGabriel Fernandez 796*9be88e75SGabriel Fernandez while ((mmio_read_32(address) & mask) == 0U) { 797*9be88e75SGabriel Fernandez if (timeout_elapsed(timeout)) { 798*9be88e75SGabriel Fernandez return -ETIMEDOUT; 799*9be88e75SGabriel Fernandez } 800*9be88e75SGabriel Fernandez } 801*9be88e75SGabriel Fernandez 802*9be88e75SGabriel Fernandez return 0; 803*9be88e75SGabriel Fernandez } 804*9be88e75SGabriel Fernandez 805*9be88e75SGabriel Fernandez int _clk_stm32_gate_wait_ready(struct stm32_clk_priv *priv, uint16_t gate_id, 806*9be88e75SGabriel Fernandez bool ready_on) 807*9be88e75SGabriel Fernandez { 808*9be88e75SGabriel Fernandez const struct gate_cfg *gate = &priv->gates[gate_id]; 809*9be88e75SGabriel Fernandez uintptr_t address = priv->base + gate->offset; 810*9be88e75SGabriel Fernandez uint32_t mask_rdy = BIT(gate->bit_idx); 811*9be88e75SGabriel Fernandez uint64_t timeout; 812*9be88e75SGabriel Fernandez uint32_t mask_test; 813*9be88e75SGabriel Fernandez 814*9be88e75SGabriel Fernandez if (ready_on) { 815*9be88e75SGabriel Fernandez mask_test = BIT(gate->bit_idx); 816*9be88e75SGabriel Fernandez } else { 817*9be88e75SGabriel Fernandez mask_test = 0U; 818*9be88e75SGabriel Fernandez } 819*9be88e75SGabriel Fernandez 820*9be88e75SGabriel Fernandez timeout = timeout_init_us(OSCRDY_TIMEOUT); 821*9be88e75SGabriel Fernandez 822*9be88e75SGabriel Fernandez while ((mmio_read_32(address) & mask_rdy) != mask_test) { 823*9be88e75SGabriel Fernandez if (timeout_elapsed(timeout)) { 824*9be88e75SGabriel Fernandez break; 825*9be88e75SGabriel Fernandez } 826*9be88e75SGabriel Fernandez } 827*9be88e75SGabriel Fernandez 828*9be88e75SGabriel Fernandez if ((mmio_read_32(address) & mask_rdy) != mask_test) 829*9be88e75SGabriel Fernandez return -ETIMEDOUT; 830*9be88e75SGabriel Fernandez 831*9be88e75SGabriel Fernandez return 0; 832*9be88e75SGabriel Fernandez } 833*9be88e75SGabriel Fernandez 834*9be88e75SGabriel Fernandez int clk_stm32_gate_enable(struct stm32_clk_priv *priv, int id) 835*9be88e75SGabriel Fernandez { 836*9be88e75SGabriel Fernandez const struct clk_stm32 *clk = _clk_get(priv, id); 837*9be88e75SGabriel Fernandez struct clk_stm32_gate_cfg *cfg = clk->clock_cfg; 838*9be88e75SGabriel Fernandez const struct gate_cfg *gate = &priv->gates[cfg->id]; 839*9be88e75SGabriel Fernandez uintptr_t addr = priv->base + gate->offset; 840*9be88e75SGabriel Fernandez 841*9be88e75SGabriel Fernandez if (gate->set_clr != 0U) { 842*9be88e75SGabriel Fernandez mmio_write_32(addr, BIT(gate->bit_idx)); 843*9be88e75SGabriel Fernandez 844*9be88e75SGabriel Fernandez } else { 845*9be88e75SGabriel Fernandez mmio_setbits_32(addr, BIT(gate->bit_idx)); 846*9be88e75SGabriel Fernandez } 847*9be88e75SGabriel Fernandez 848*9be88e75SGabriel Fernandez return 0; 849*9be88e75SGabriel Fernandez } 850*9be88e75SGabriel Fernandez 851*9be88e75SGabriel Fernandez void clk_stm32_gate_disable(struct stm32_clk_priv *priv, int id) 852*9be88e75SGabriel Fernandez { 853*9be88e75SGabriel Fernandez const struct clk_stm32 *clk = _clk_get(priv, id); 854*9be88e75SGabriel Fernandez struct clk_stm32_gate_cfg *cfg = clk->clock_cfg; 855*9be88e75SGabriel Fernandez const struct gate_cfg *gate = &priv->gates[cfg->id]; 856*9be88e75SGabriel Fernandez uintptr_t addr = priv->base + gate->offset; 857*9be88e75SGabriel Fernandez 858*9be88e75SGabriel Fernandez if (gate->set_clr != 0U) { 859*9be88e75SGabriel Fernandez mmio_write_32(addr + RCC_MP_ENCLRR_OFFSET, BIT(gate->bit_idx)); 860*9be88e75SGabriel Fernandez } else { 861*9be88e75SGabriel Fernandez mmio_clrbits_32(addr, BIT(gate->bit_idx)); 862*9be88e75SGabriel Fernandez } 863*9be88e75SGabriel Fernandez } 864*9be88e75SGabriel Fernandez 865*9be88e75SGabriel Fernandez bool _clk_stm32_gate_is_enabled(struct stm32_clk_priv *priv, int gate_id) 866*9be88e75SGabriel Fernandez { 867*9be88e75SGabriel Fernandez const struct gate_cfg *gate; 868*9be88e75SGabriel Fernandez uint32_t addr; 869*9be88e75SGabriel Fernandez 870*9be88e75SGabriel Fernandez gate = &priv->gates[gate_id]; 871*9be88e75SGabriel Fernandez addr = priv->base + gate->offset; 872*9be88e75SGabriel Fernandez 873*9be88e75SGabriel Fernandez return ((mmio_read_32(addr) & BIT(gate->bit_idx)) != 0U); 874*9be88e75SGabriel Fernandez } 875*9be88e75SGabriel Fernandez 876*9be88e75SGabriel Fernandez bool clk_stm32_gate_is_enabled(struct stm32_clk_priv *priv, int id) 877*9be88e75SGabriel Fernandez { 878*9be88e75SGabriel Fernandez const struct clk_stm32 *clk = _clk_get(priv, id); 879*9be88e75SGabriel Fernandez struct clk_stm32_gate_cfg *cfg = clk->clock_cfg; 880*9be88e75SGabriel Fernandez 881*9be88e75SGabriel Fernandez return _clk_stm32_gate_is_enabled(priv, cfg->id); 882*9be88e75SGabriel Fernandez } 883*9be88e75SGabriel Fernandez 884*9be88e75SGabriel Fernandez const struct stm32_clk_ops clk_stm32_gate_ops = { 885*9be88e75SGabriel Fernandez .enable = clk_stm32_gate_enable, 886*9be88e75SGabriel Fernandez .disable = clk_stm32_gate_disable, 887*9be88e75SGabriel Fernandez .is_enabled = clk_stm32_gate_is_enabled, 888*9be88e75SGabriel Fernandez }; 889*9be88e75SGabriel Fernandez 890*9be88e75SGabriel Fernandez const struct stm32_clk_ops clk_fixed_factor_ops = { 891*9be88e75SGabriel Fernandez .recalc_rate = fixed_factor_recalc_rate, 892*9be88e75SGabriel Fernandez }; 893*9be88e75SGabriel Fernandez 894*9be88e75SGabriel Fernandez unsigned long fixed_factor_recalc_rate(struct stm32_clk_priv *priv, 895*9be88e75SGabriel Fernandez int id, unsigned long prate) 896*9be88e75SGabriel Fernandez { 897*9be88e75SGabriel Fernandez const struct clk_stm32 *clk = _clk_get(priv, id); 898*9be88e75SGabriel Fernandez const struct fixed_factor_cfg *cfg = clk->clock_cfg; 899*9be88e75SGabriel Fernandez unsigned long long rate; 900*9be88e75SGabriel Fernandez 901*9be88e75SGabriel Fernandez rate = (unsigned long long)prate * cfg->mult; 902*9be88e75SGabriel Fernandez 903*9be88e75SGabriel Fernandez if (cfg->div == 0U) { 904*9be88e75SGabriel Fernandez ERROR("division by zero\n"); 905*9be88e75SGabriel Fernandez panic(); 906*9be88e75SGabriel Fernandez } 907*9be88e75SGabriel Fernandez 908*9be88e75SGabriel Fernandez return (unsigned long)(rate / cfg->div); 909*9be88e75SGabriel Fernandez }; 910*9be88e75SGabriel Fernandez 911*9be88e75SGabriel Fernandez #define APB_DIV_MASK GENMASK(2, 0) 912*9be88e75SGabriel Fernandez #define TIM_PRE_MASK BIT(0) 913*9be88e75SGabriel Fernandez 914*9be88e75SGabriel Fernandez static unsigned long timer_recalc_rate(struct stm32_clk_priv *priv, 915*9be88e75SGabriel Fernandez int id, unsigned long prate) 916*9be88e75SGabriel Fernandez { 917*9be88e75SGabriel Fernandez const struct clk_stm32 *clk = _clk_get(priv, id); 918*9be88e75SGabriel Fernandez const struct clk_timer_cfg *cfg = clk->clock_cfg; 919*9be88e75SGabriel Fernandez uint32_t prescaler, timpre; 920*9be88e75SGabriel Fernandez uintptr_t rcc_base = priv->base; 921*9be88e75SGabriel Fernandez 922*9be88e75SGabriel Fernandez prescaler = mmio_read_32(rcc_base + cfg->apbdiv) & 923*9be88e75SGabriel Fernandez APB_DIV_MASK; 924*9be88e75SGabriel Fernandez 925*9be88e75SGabriel Fernandez timpre = mmio_read_32(rcc_base + cfg->timpre) & 926*9be88e75SGabriel Fernandez TIM_PRE_MASK; 927*9be88e75SGabriel Fernandez 928*9be88e75SGabriel Fernandez if (prescaler == 0U) { 929*9be88e75SGabriel Fernandez return prate; 930*9be88e75SGabriel Fernandez } 931*9be88e75SGabriel Fernandez 932*9be88e75SGabriel Fernandez return prate * (timpre + 1U) * 2U; 933*9be88e75SGabriel Fernandez }; 934*9be88e75SGabriel Fernandez 935*9be88e75SGabriel Fernandez const struct stm32_clk_ops clk_timer_ops = { 936*9be88e75SGabriel Fernandez .recalc_rate = timer_recalc_rate, 937*9be88e75SGabriel Fernandez }; 938*9be88e75SGabriel Fernandez 939*9be88e75SGabriel Fernandez static unsigned long clk_fixed_rate_recalc(struct stm32_clk_priv *priv, int id, 940*9be88e75SGabriel Fernandez unsigned long prate) 941*9be88e75SGabriel Fernandez { 942*9be88e75SGabriel Fernandez const struct clk_stm32 *clk = _clk_get(priv, id); 943*9be88e75SGabriel Fernandez struct clk_stm32_fixed_rate_cfg *cfg = clk->clock_cfg; 944*9be88e75SGabriel Fernandez 945*9be88e75SGabriel Fernandez return cfg->rate; 946*9be88e75SGabriel Fernandez } 947*9be88e75SGabriel Fernandez 948*9be88e75SGabriel Fernandez const struct stm32_clk_ops clk_stm32_fixed_rate_ops = { 949*9be88e75SGabriel Fernandez .recalc_rate = clk_fixed_rate_recalc, 950*9be88e75SGabriel Fernandez }; 951*9be88e75SGabriel Fernandez 952*9be88e75SGabriel Fernandez static unsigned long clk_stm32_osc_recalc_rate(struct stm32_clk_priv *priv, 953*9be88e75SGabriel Fernandez int id, unsigned long prate) 954*9be88e75SGabriel Fernandez { 955*9be88e75SGabriel Fernandez struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); 956*9be88e75SGabriel Fernandez 957*9be88e75SGabriel Fernandez return osc_data->frequency; 958*9be88e75SGabriel Fernandez }; 959*9be88e75SGabriel Fernandez 960*9be88e75SGabriel Fernandez bool clk_stm32_osc_gate_is_enabled(struct stm32_clk_priv *priv, int id) 961*9be88e75SGabriel Fernandez { 962*9be88e75SGabriel Fernandez struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); 963*9be88e75SGabriel Fernandez 964*9be88e75SGabriel Fernandez return _clk_stm32_gate_is_enabled(priv, osc_data->gate_id); 965*9be88e75SGabriel Fernandez 966*9be88e75SGabriel Fernandez } 967*9be88e75SGabriel Fernandez 968*9be88e75SGabriel Fernandez int clk_stm32_osc_gate_enable(struct stm32_clk_priv *priv, int id) 969*9be88e75SGabriel Fernandez { 970*9be88e75SGabriel Fernandez struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); 971*9be88e75SGabriel Fernandez 972*9be88e75SGabriel Fernandez _clk_stm32_gate_enable(priv, osc_data->gate_id); 973*9be88e75SGabriel Fernandez 974*9be88e75SGabriel Fernandez if (_clk_stm32_gate_wait_ready(priv, osc_data->gate_rdy_id, true) != 0U) { 975*9be88e75SGabriel Fernandez ERROR("%s: %s (%d)\n", __func__, osc_data->name, __LINE__); 976*9be88e75SGabriel Fernandez panic(); 977*9be88e75SGabriel Fernandez } 978*9be88e75SGabriel Fernandez 979*9be88e75SGabriel Fernandez return 0; 980*9be88e75SGabriel Fernandez } 981*9be88e75SGabriel Fernandez 982*9be88e75SGabriel Fernandez void clk_stm32_osc_gate_disable(struct stm32_clk_priv *priv, int id) 983*9be88e75SGabriel Fernandez { 984*9be88e75SGabriel Fernandez struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); 985*9be88e75SGabriel Fernandez 986*9be88e75SGabriel Fernandez _clk_stm32_gate_disable(priv, osc_data->gate_id); 987*9be88e75SGabriel Fernandez 988*9be88e75SGabriel Fernandez if (_clk_stm32_gate_wait_ready(priv, osc_data->gate_rdy_id, false) != 0U) { 989*9be88e75SGabriel Fernandez ERROR("%s: %s (%d)\n", __func__, osc_data->name, __LINE__); 990*9be88e75SGabriel Fernandez panic(); 991*9be88e75SGabriel Fernandez } 992*9be88e75SGabriel Fernandez } 993*9be88e75SGabriel Fernandez 994*9be88e75SGabriel Fernandez static unsigned long clk_stm32_get_dt_oscillator_frequency(const char *name) 995*9be88e75SGabriel Fernandez { 996*9be88e75SGabriel Fernandez void *fdt = NULL; 997*9be88e75SGabriel Fernandez int node = 0; 998*9be88e75SGabriel Fernandez int subnode = 0; 999*9be88e75SGabriel Fernandez 1000*9be88e75SGabriel Fernandez if (fdt_get_address(&fdt) == 0) { 1001*9be88e75SGabriel Fernandez panic(); 1002*9be88e75SGabriel Fernandez } 1003*9be88e75SGabriel Fernandez 1004*9be88e75SGabriel Fernandez node = fdt_path_offset(fdt, "/clocks"); 1005*9be88e75SGabriel Fernandez if (node < 0) { 1006*9be88e75SGabriel Fernandez return 0UL; 1007*9be88e75SGabriel Fernandez } 1008*9be88e75SGabriel Fernandez 1009*9be88e75SGabriel Fernandez fdt_for_each_subnode(subnode, fdt, node) { 1010*9be88e75SGabriel Fernandez const char *cchar = NULL; 1011*9be88e75SGabriel Fernandez const fdt32_t *cuint = NULL; 1012*9be88e75SGabriel Fernandez int ret = 0; 1013*9be88e75SGabriel Fernandez 1014*9be88e75SGabriel Fernandez cchar = fdt_get_name(fdt, subnode, &ret); 1015*9be88e75SGabriel Fernandez if (cchar == NULL) { 1016*9be88e75SGabriel Fernandez continue; 1017*9be88e75SGabriel Fernandez } 1018*9be88e75SGabriel Fernandez 1019*9be88e75SGabriel Fernandez if (strncmp(cchar, name, (size_t)ret) || 1020*9be88e75SGabriel Fernandez fdt_get_status(subnode) == DT_DISABLED) { 1021*9be88e75SGabriel Fernandez continue; 1022*9be88e75SGabriel Fernandez } 1023*9be88e75SGabriel Fernandez 1024*9be88e75SGabriel Fernandez cuint = fdt_getprop(fdt, subnode, "clock-frequency", &ret); 1025*9be88e75SGabriel Fernandez if (cuint == NULL) { 1026*9be88e75SGabriel Fernandez return 0UL; 1027*9be88e75SGabriel Fernandez } 1028*9be88e75SGabriel Fernandez 1029*9be88e75SGabriel Fernandez return fdt32_to_cpu(*cuint); 1030*9be88e75SGabriel Fernandez } 1031*9be88e75SGabriel Fernandez 1032*9be88e75SGabriel Fernandez return 0UL; 1033*9be88e75SGabriel Fernandez } 1034*9be88e75SGabriel Fernandez 1035*9be88e75SGabriel Fernandez void clk_stm32_osc_init(struct stm32_clk_priv *priv, int id) 1036*9be88e75SGabriel Fernandez { 1037*9be88e75SGabriel Fernandez struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); 1038*9be88e75SGabriel Fernandez const char *name = osc_data->name; 1039*9be88e75SGabriel Fernandez 1040*9be88e75SGabriel Fernandez osc_data->frequency = clk_stm32_get_dt_oscillator_frequency(name); 1041*9be88e75SGabriel Fernandez } 1042*9be88e75SGabriel Fernandez 1043*9be88e75SGabriel Fernandez const struct stm32_clk_ops clk_stm32_osc_ops = { 1044*9be88e75SGabriel Fernandez .recalc_rate = clk_stm32_osc_recalc_rate, 1045*9be88e75SGabriel Fernandez .is_enabled = clk_stm32_osc_gate_is_enabled, 1046*9be88e75SGabriel Fernandez .enable = clk_stm32_osc_gate_enable, 1047*9be88e75SGabriel Fernandez .disable = clk_stm32_osc_gate_disable, 1048*9be88e75SGabriel Fernandez .init = clk_stm32_osc_init, 1049*9be88e75SGabriel Fernandez }; 1050*9be88e75SGabriel Fernandez 1051*9be88e75SGabriel Fernandez const struct stm32_clk_ops clk_stm32_osc_nogate_ops = { 1052*9be88e75SGabriel Fernandez .recalc_rate = clk_stm32_osc_recalc_rate, 1053*9be88e75SGabriel Fernandez .init = clk_stm32_osc_init, 1054*9be88e75SGabriel Fernandez }; 1055*9be88e75SGabriel Fernandez 1056*9be88e75SGabriel Fernandez int stm32_clk_parse_fdt_by_name(void *fdt, int node, const char *name, uint32_t *tab, uint32_t *nb) 1057*9be88e75SGabriel Fernandez { 1058*9be88e75SGabriel Fernandez const fdt32_t *cell; 1059*9be88e75SGabriel Fernandez int len = 0; 1060*9be88e75SGabriel Fernandez uint32_t i; 1061*9be88e75SGabriel Fernandez 1062*9be88e75SGabriel Fernandez cell = fdt_getprop(fdt, node, name, &len); 1063*9be88e75SGabriel Fernandez if (cell != NULL) { 1064*9be88e75SGabriel Fernandez for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) { 1065*9be88e75SGabriel Fernandez uint32_t val = fdt32_to_cpu(cell[i]); 1066*9be88e75SGabriel Fernandez 1067*9be88e75SGabriel Fernandez tab[i] = val; 1068*9be88e75SGabriel Fernandez } 1069*9be88e75SGabriel Fernandez } 1070*9be88e75SGabriel Fernandez 1071*9be88e75SGabriel Fernandez *nb = (uint32_t)len / sizeof(uint32_t); 1072*9be88e75SGabriel Fernandez 1073*9be88e75SGabriel Fernandez return 0; 1074*9be88e75SGabriel Fernandez } 1075*9be88e75SGabriel Fernandez 1076*9be88e75SGabriel Fernandez int clk_stm32_init(struct stm32_clk_priv *priv, uintptr_t base) 1077*9be88e75SGabriel Fernandez { 1078*9be88e75SGabriel Fernandez unsigned int i; 1079*9be88e75SGabriel Fernandez 1080*9be88e75SGabriel Fernandez stm32_clock_data = priv; 1081*9be88e75SGabriel Fernandez 1082*9be88e75SGabriel Fernandez priv->base = base; 1083*9be88e75SGabriel Fernandez 1084*9be88e75SGabriel Fernandez for (i = 0U; i < priv->num; i++) { 1085*9be88e75SGabriel Fernandez const struct clk_stm32 *clk = _clk_get(priv, i); 1086*9be88e75SGabriel Fernandez 1087*9be88e75SGabriel Fernandez assert(clk->ops != NULL); 1088*9be88e75SGabriel Fernandez 1089*9be88e75SGabriel Fernandez if (clk->ops->init != NULL) { 1090*9be88e75SGabriel Fernandez clk->ops->init(priv, i); 1091*9be88e75SGabriel Fernandez } 1092*9be88e75SGabriel Fernandez } 1093*9be88e75SGabriel Fernandez 1094*9be88e75SGabriel Fernandez stm32_clk_register(); 1095*9be88e75SGabriel Fernandez 1096*9be88e75SGabriel Fernandez return 0; 1097*9be88e75SGabriel Fernandez } 1098