1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
| static const struct clk_cfg clk_map[] = {}; static ulong stm32_clk_get_rate(struct clk *clk) { struct stm32_clk *priv = dev_get_priv(clk->dev); struct stm32_rcc_regs *regs = priv->rcc_base; ulong sysclk = 0; u32 gate_offset; u32 d1cfgr, d3cfgr; u16 prescaler_table[8] = {2, 4, 8, 16, 64, 128, 256, 512}; u8 source, idx;
source = readl(®s->cfgr) & RCC_CFGR_SW_MASK; switch (source) { case RCC_CFGR_SW_PLL1: sysclk = stm32_get_PLL1_rate(regs, PLL1_P_CK); break; case RCC_CFGR_SW_HSE: sysclk = stm32_get_rate(regs, HSE); break;
case RCC_CFGR_SW_CSI: sysclk = stm32_get_rate(regs, CSI); break;
case RCC_CFGR_SW_HSI: sysclk = stm32_get_rate(regs, HSI); break; }
if (!sysclk) return sysclk;
dev_dbg(clk->dev, "system clock: source = %d freq = %ld\n", source, sysclk);
d1cfgr = readl(®s->d1cfgr);
if (d1cfgr & RCC_D1CFGR_D1CPRE_DIVIDED) { idx = (d1cfgr & RCC_D1CFGR_D1CPRE_DIVIDER) >> RCC_D1CFGR_D1CPRE_SHIFT; sysclk = sysclk / prescaler_table[idx]; }
if (d1cfgr & RCC_D1CFGR_HPRE_DIVIDED) { idx = d1cfgr & RCC_D1CFGR_HPRE_DIVIDER; sysclk = sysclk / prescaler_table[idx]; }
gate_offset = clk_map[clk->id].gate_offset;
dev_dbg(clk->dev, "clk->id=%ld gate_offset=0x%x sysclk=%ld\n", clk->id, gate_offset, sysclk);
switch (gate_offset) { case RCC_AHB3ENR: case RCC_AHB1ENR: case RCC_AHB2ENR: case RCC_AHB4ENR: return sysclk; break;
case RCC_APB3ENR: if (d1cfgr & RCC_D1CFGR_D1PPRE_DIVIDED) { idx = (d1cfgr & RCC_D1CFGR_D1PPRE_DIVIDER) >> RCC_D1CFGR_D1PPRE_SHIFT; sysclk = sysclk / prescaler_table[idx]; }
dev_dbg(clk->dev, "system clock: freq after APB3 prescaler = %ld\n", sysclk);
return sysclk; break;
case RCC_APB4ENR: d3cfgr = readl(®s->d3cfgr); if (d3cfgr & RCC_D3CFGR_D3PPRE_DIVIDED) { idx = (d3cfgr & RCC_D3CFGR_D3PPRE_DIVIDER) >> RCC_D3CFGR_D3PPRE_SHIFT; sysclk = sysclk / prescaler_table[idx]; }
dev_dbg(clk->dev, "system clock: freq after APB4 prescaler = %ld\n", sysclk);
return sysclk; break;
case RCC_APB1LENR: case RCC_APB1HENR: switch (clk->id) { case TIM14_CK: case TIM13_CK: case TIM12_CK: case TIM7_CK: case TIM6_CK: case TIM5_CK: case TIM4_CK: case TIM3_CK: case TIM2_CK: return stm32_get_timer_rate(priv, sysclk, APB1); }
dev_dbg(clk->dev, "system clock: freq after APB1 prescaler = %ld\n", sysclk);
return (sysclk / stm32_get_apb_psc(regs, APB1)); break;
case RCC_APB2ENR: switch (clk->id) { case TIM17_CK: case TIM16_CK: case TIM15_CK: case TIM8_CK: case TIM1_CK: return stm32_get_timer_rate(priv, sysclk, APB2); }
dev_dbg(clk->dev, "system clock: freq after APB2 prescaler = %ld\n", sysclk);
return (sysclk / stm32_get_apb_psc(regs, APB2));
break;
default: dev_err(clk->dev, "unexpected gate_offset value (0x%x)\n", gate_offset); return -EINVAL; break; } }
|