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