1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * (C) Copyright 2018 - Beniamino Galvani <b.galvani@gmail.com> 4 * (C) Copyright 2018 - BayLibre, SAS 5 * Author: Neil Armstrong <narmstrong@baylibre.com> 6 */ 7 8 #include <common.h> 9 #include <asm/arch/clock.h> 10 #include <asm/io.h> 11 #include <clk-uclass.h> 12 #include <div64.h> 13 #include <dm.h> 14 #include <dt-bindings/clock/gxbb-clkc.h> 15 #include "clk_meson.h" 16 17 /* This driver support only basic clock tree operations : 18 * - Can calculate clock frequency on a limited tree 19 * - Can Read muxes and basic dividers (0-based only) 20 * - Can enable/disable gates with limited propagation 21 * - Can reparent without propagation, only on muxes 22 * - Can set rates without reparenting 23 * This driver is adapted to what is actually supported by U-Boot 24 */ 25 26 /* Only the clocks ids we don't want to expose, such as the internal muxes 27 * and dividers of composite clocks, will remain defined here. 28 */ 29 #define CLKID_MPEG_SEL 10 30 #define CLKID_MPEG_DIV 11 31 #define CLKID_SAR_ADC_DIV 99 32 #define CLKID_MALI_0_DIV 101 33 #define CLKID_MALI_1_DIV 104 34 #define CLKID_CTS_AMCLK_SEL 108 35 #define CLKID_CTS_AMCLK_DIV 109 36 #define CLKID_CTS_MCLK_I958_SEL 111 37 #define CLKID_CTS_MCLK_I958_DIV 112 38 #define CLKID_32K_CLK_SEL 115 39 #define CLKID_32K_CLK_DIV 116 40 #define CLKID_SD_EMMC_A_CLK0_SEL 117 41 #define CLKID_SD_EMMC_A_CLK0_DIV 118 42 #define CLKID_SD_EMMC_B_CLK0_SEL 120 43 #define CLKID_SD_EMMC_B_CLK0_DIV 121 44 #define CLKID_SD_EMMC_C_CLK0_SEL 123 45 #define CLKID_SD_EMMC_C_CLK0_DIV 124 46 #define CLKID_VPU_0_DIV 127 47 #define CLKID_VPU_1_DIV 130 48 #define CLKID_VAPB_0_DIV 134 49 #define CLKID_VAPB_1_DIV 137 50 #define CLKID_HDMI_PLL_PRE_MULT 141 51 #define CLKID_MPLL0_DIV 142 52 #define CLKID_MPLL1_DIV 143 53 #define CLKID_MPLL2_DIV 144 54 #define CLKID_MPLL_PREDIV 145 55 #define CLKID_FCLK_DIV2_DIV 146 56 #define CLKID_FCLK_DIV3_DIV 147 57 #define CLKID_FCLK_DIV4_DIV 148 58 #define CLKID_FCLK_DIV5_DIV 149 59 #define CLKID_FCLK_DIV7_DIV 150 60 #define CLKID_VDEC_1_SEL 151 61 #define CLKID_VDEC_1_DIV 152 62 #define CLKID_VDEC_HEVC_SEL 154 63 #define CLKID_VDEC_HEVC_DIV 155 64 65 #define XTAL_RATE 24000000 66 67 struct meson_clk { 68 void __iomem *addr; 69 }; 70 71 static ulong meson_div_get_rate(struct clk *clk, unsigned long id); 72 static ulong meson_div_set_rate(struct clk *clk, unsigned long id, ulong rate, 73 ulong current_rate); 74 static ulong meson_mux_set_parent(struct clk *clk, unsigned long id, 75 unsigned long parent_id); 76 static ulong meson_mux_get_rate(struct clk *clk, unsigned long id); 77 static ulong meson_clk_set_rate_by_id(struct clk *clk, unsigned long id, 78 ulong rate, ulong current_rate); 79 static ulong meson_mux_get_parent(struct clk *clk, unsigned long id); 80 static ulong meson_clk_get_rate_by_id(struct clk *clk, unsigned long id); 81 82 struct meson_gate gates[] = { 83 /* Everything Else (EE) domain gates */ 84 MESON_GATE(CLKID_DDR, HHI_GCLK_MPEG0, 0), 85 MESON_GATE(CLKID_DOS, HHI_GCLK_MPEG0, 1), 86 MESON_GATE(CLKID_ISA, HHI_GCLK_MPEG0, 5), 87 MESON_GATE(CLKID_PL301, HHI_GCLK_MPEG0, 6), 88 MESON_GATE(CLKID_PERIPHS, HHI_GCLK_MPEG0, 7), 89 MESON_GATE(CLKID_SPICC, HHI_GCLK_MPEG0, 8), 90 MESON_GATE(CLKID_I2C, HHI_GCLK_MPEG0, 9), 91 MESON_GATE(CLKID_SAR_ADC, HHI_GCLK_MPEG0, 10), 92 MESON_GATE(CLKID_SMART_CARD, HHI_GCLK_MPEG0, 11), 93 MESON_GATE(CLKID_RNG0, HHI_GCLK_MPEG0, 12), 94 MESON_GATE(CLKID_UART0, HHI_GCLK_MPEG0, 13), 95 MESON_GATE(CLKID_SDHC, HHI_GCLK_MPEG0, 14), 96 MESON_GATE(CLKID_STREAM, HHI_GCLK_MPEG0, 15), 97 MESON_GATE(CLKID_ASYNC_FIFO, HHI_GCLK_MPEG0, 16), 98 MESON_GATE(CLKID_SDIO, HHI_GCLK_MPEG0, 17), 99 MESON_GATE(CLKID_ABUF, HHI_GCLK_MPEG0, 18), 100 MESON_GATE(CLKID_HIU_IFACE, HHI_GCLK_MPEG0, 19), 101 MESON_GATE(CLKID_ASSIST_MISC, HHI_GCLK_MPEG0, 23), 102 MESON_GATE(CLKID_SD_EMMC_A, HHI_GCLK_MPEG0, 24), 103 MESON_GATE(CLKID_SD_EMMC_B, HHI_GCLK_MPEG0, 25), 104 MESON_GATE(CLKID_SD_EMMC_C, HHI_GCLK_MPEG0, 26), 105 MESON_GATE(CLKID_SPI, HHI_GCLK_MPEG0, 30), 106 107 MESON_GATE(CLKID_I2S_SPDIF, HHI_GCLK_MPEG1, 2), 108 MESON_GATE(CLKID_ETH, HHI_GCLK_MPEG1, 3), 109 MESON_GATE(CLKID_DEMUX, HHI_GCLK_MPEG1, 4), 110 MESON_GATE(CLKID_AIU_GLUE, HHI_GCLK_MPEG1, 6), 111 MESON_GATE(CLKID_IEC958, HHI_GCLK_MPEG1, 7), 112 MESON_GATE(CLKID_I2S_OUT, HHI_GCLK_MPEG1, 8), 113 MESON_GATE(CLKID_AMCLK, HHI_GCLK_MPEG1, 9), 114 MESON_GATE(CLKID_AIFIFO2, HHI_GCLK_MPEG1, 10), 115 MESON_GATE(CLKID_MIXER, HHI_GCLK_MPEG1, 11), 116 MESON_GATE(CLKID_MIXER_IFACE, HHI_GCLK_MPEG1, 12), 117 MESON_GATE(CLKID_ADC, HHI_GCLK_MPEG1, 13), 118 MESON_GATE(CLKID_BLKMV, HHI_GCLK_MPEG1, 14), 119 MESON_GATE(CLKID_AIU, HHI_GCLK_MPEG1, 15), 120 MESON_GATE(CLKID_UART1, HHI_GCLK_MPEG1, 16), 121 MESON_GATE(CLKID_G2D, HHI_GCLK_MPEG1, 20), 122 MESON_GATE(CLKID_USB0, HHI_GCLK_MPEG1, 21), 123 MESON_GATE(CLKID_USB1, HHI_GCLK_MPEG1, 22), 124 MESON_GATE(CLKID_RESET, HHI_GCLK_MPEG1, 23), 125 MESON_GATE(CLKID_NAND, HHI_GCLK_MPEG1, 24), 126 MESON_GATE(CLKID_DOS_PARSER, HHI_GCLK_MPEG1, 25), 127 MESON_GATE(CLKID_USB, HHI_GCLK_MPEG1, 26), 128 MESON_GATE(CLKID_VDIN1, HHI_GCLK_MPEG1, 28), 129 MESON_GATE(CLKID_AHB_ARB0, HHI_GCLK_MPEG1, 29), 130 MESON_GATE(CLKID_EFUSE, HHI_GCLK_MPEG1, 30), 131 MESON_GATE(CLKID_BOOT_ROM, HHI_GCLK_MPEG1, 31), 132 133 MESON_GATE(CLKID_AHB_DATA_BUS, HHI_GCLK_MPEG2, 1), 134 MESON_GATE(CLKID_AHB_CTRL_BUS, HHI_GCLK_MPEG2, 2), 135 MESON_GATE(CLKID_HDMI_INTR_SYNC, HHI_GCLK_MPEG2, 3), 136 MESON_GATE(CLKID_HDMI_PCLK, HHI_GCLK_MPEG2, 4), 137 MESON_GATE(CLKID_USB1_DDR_BRIDGE, HHI_GCLK_MPEG2, 8), 138 MESON_GATE(CLKID_USB0_DDR_BRIDGE, HHI_GCLK_MPEG2, 9), 139 MESON_GATE(CLKID_MMC_PCLK, HHI_GCLK_MPEG2, 11), 140 MESON_GATE(CLKID_DVIN, HHI_GCLK_MPEG2, 12), 141 MESON_GATE(CLKID_UART2, HHI_GCLK_MPEG2, 15), 142 MESON_GATE(CLKID_SANA, HHI_GCLK_MPEG2, 22), 143 MESON_GATE(CLKID_VPU_INTR, HHI_GCLK_MPEG2, 25), 144 MESON_GATE(CLKID_SEC_AHB_AHB3_BRIDGE, HHI_GCLK_MPEG2, 26), 145 MESON_GATE(CLKID_CLK81_A53, HHI_GCLK_MPEG2, 29), 146 147 MESON_GATE(CLKID_VCLK2_VENCI0, HHI_GCLK_OTHER, 1), 148 MESON_GATE(CLKID_VCLK2_VENCI1, HHI_GCLK_OTHER, 2), 149 MESON_GATE(CLKID_VCLK2_VENCP0, HHI_GCLK_OTHER, 3), 150 MESON_GATE(CLKID_VCLK2_VENCP1, HHI_GCLK_OTHER, 4), 151 MESON_GATE(CLKID_GCLK_VENCI_INT0, HHI_GCLK_OTHER, 8), 152 MESON_GATE(CLKID_DAC_CLK, HHI_GCLK_OTHER, 10), 153 MESON_GATE(CLKID_AOCLK_GATE, HHI_GCLK_OTHER, 14), 154 MESON_GATE(CLKID_IEC958_GATE, HHI_GCLK_OTHER, 16), 155 MESON_GATE(CLKID_ENC480P, HHI_GCLK_OTHER, 20), 156 MESON_GATE(CLKID_RNG1, HHI_GCLK_OTHER, 21), 157 MESON_GATE(CLKID_GCLK_VENCI_INT1, HHI_GCLK_OTHER, 22), 158 MESON_GATE(CLKID_VCLK2_VENCLMCC, HHI_GCLK_OTHER, 24), 159 MESON_GATE(CLKID_VCLK2_VENCL, HHI_GCLK_OTHER, 25), 160 MESON_GATE(CLKID_VCLK_OTHER, HHI_GCLK_OTHER, 26), 161 MESON_GATE(CLKID_EDP, HHI_GCLK_OTHER, 31), 162 163 /* Always On (AO) domain gates */ 164 MESON_GATE(CLKID_AO_MEDIA_CPU, HHI_GCLK_AO, 0), 165 MESON_GATE(CLKID_AO_AHB_SRAM, HHI_GCLK_AO, 1), 166 MESON_GATE(CLKID_AO_AHB_BUS, HHI_GCLK_AO, 2), 167 MESON_GATE(CLKID_AO_IFACE, HHI_GCLK_AO, 3), 168 MESON_GATE(CLKID_AO_I2C, HHI_GCLK_AO, 4), 169 170 /* PLL Gates */ 171 /* CLKID_FCLK_DIV2 is critical for the SCPI Processor */ 172 MESON_GATE(CLKID_FCLK_DIV3, HHI_MPLL_CNTL6, 28), 173 MESON_GATE(CLKID_FCLK_DIV4, HHI_MPLL_CNTL6, 29), 174 MESON_GATE(CLKID_FCLK_DIV5, HHI_MPLL_CNTL6, 30), 175 MESON_GATE(CLKID_FCLK_DIV7, HHI_MPLL_CNTL6, 31), 176 MESON_GATE(CLKID_MPLL0, HHI_MPLL_CNTL7, 14), 177 MESON_GATE(CLKID_MPLL1, HHI_MPLL_CNTL8, 14), 178 MESON_GATE(CLKID_MPLL2, HHI_MPLL_CNTL9, 14), 179 /* CLKID_CLK81 is critical for the system */ 180 181 /* Peripheral Gates */ 182 MESON_GATE(CLKID_SAR_ADC_CLK, HHI_SAR_CLK_CNTL, 8), 183 MESON_GATE(CLKID_SD_EMMC_A_CLK0, HHI_SD_EMMC_CLK_CNTL, 7), 184 MESON_GATE(CLKID_SD_EMMC_B_CLK0, HHI_SD_EMMC_CLK_CNTL, 23), 185 MESON_GATE(CLKID_SD_EMMC_C_CLK0, HHI_NAND_CLK_CNTL, 7), 186 MESON_GATE(CLKID_VPU_0, HHI_VPU_CLK_CNTL, 8), 187 MESON_GATE(CLKID_VPU_1, HHI_VPU_CLK_CNTL, 24), 188 MESON_GATE(CLKID_VAPB_0, HHI_VAPBCLK_CNTL, 8), 189 MESON_GATE(CLKID_VAPB_1, HHI_VAPBCLK_CNTL, 24), 190 MESON_GATE(CLKID_VAPB, HHI_VAPBCLK_CNTL, 30), 191 }; 192 193 static int meson_set_gate_by_id(struct clk *clk, unsigned long id, bool on) 194 { 195 struct meson_clk *priv = dev_get_priv(clk->dev); 196 struct meson_gate *gate; 197 198 debug("%s: %sabling %ld\n", __func__, on ? "en" : "dis", id); 199 200 /* Propagate through muxes */ 201 switch (id) { 202 case CLKID_VPU: 203 return meson_set_gate_by_id(clk, 204 meson_mux_get_parent(clk, CLKID_VPU), on); 205 case CLKID_VAPB_SEL: 206 return meson_set_gate_by_id(clk, 207 meson_mux_get_parent(clk, CLKID_VAPB_SEL), on); 208 } 209 210 if (id >= ARRAY_SIZE(gates)) 211 return -ENOENT; 212 213 gate = &gates[id]; 214 215 if (gate->reg == 0) 216 return 0; 217 218 debug("%s: really %sabling %ld\n", __func__, on ? "en" : "dis", id); 219 220 clrsetbits_le32(priv->addr + gate->reg, 221 BIT(gate->bit), on ? BIT(gate->bit) : 0); 222 223 /* Propagate to next gate(s) */ 224 switch (id) { 225 case CLKID_VAPB: 226 return meson_set_gate_by_id(clk, CLKID_VAPB_SEL, on); 227 } 228 229 return 0; 230 } 231 232 static int meson_clk_enable(struct clk *clk) 233 { 234 return meson_set_gate_by_id(clk, clk->id, true); 235 } 236 237 static int meson_clk_disable(struct clk *clk) 238 { 239 return meson_set_gate_by_id(clk, clk->id, false); 240 } 241 242 static struct parm meson_vpu_0_div_parm = { 243 HHI_VPU_CLK_CNTL, 0, 7, 244 }; 245 246 int meson_vpu_0_div_parent = CLKID_VPU_0_SEL; 247 248 static struct parm meson_vpu_1_div_parm = { 249 HHI_VPU_CLK_CNTL, 16, 7, 250 }; 251 252 int meson_vpu_1_div_parent = CLKID_VPU_1_SEL; 253 254 static struct parm meson_vapb_0_div_parm = { 255 HHI_VAPBCLK_CNTL, 0, 7, 256 }; 257 258 int meson_vapb_0_div_parent = CLKID_VAPB_0_SEL; 259 260 static struct parm meson_vapb_1_div_parm = { 261 HHI_VAPBCLK_CNTL, 16, 7, 262 }; 263 264 int meson_vapb_1_div_parent = CLKID_VAPB_1_SEL; 265 266 static ulong meson_div_get_rate(struct clk *clk, unsigned long id) 267 { 268 struct meson_clk *priv = dev_get_priv(clk->dev); 269 unsigned int rate, parent_rate; 270 struct parm *parm; 271 int parent; 272 u32 reg; 273 274 switch (id) { 275 case CLKID_VPU_0_DIV: 276 parm = &meson_vpu_0_div_parm; 277 parent = meson_vpu_0_div_parent; 278 break; 279 case CLKID_VPU_1_DIV: 280 parm = &meson_vpu_1_div_parm; 281 parent = meson_vpu_1_div_parent; 282 break; 283 case CLKID_VAPB_0_DIV: 284 parm = &meson_vapb_0_div_parm; 285 parent = meson_vapb_0_div_parent; 286 break; 287 case CLKID_VAPB_1_DIV: 288 parm = &meson_vapb_1_div_parm; 289 parent = meson_vapb_1_div_parent; 290 break; 291 default: 292 return -ENOENT; 293 } 294 295 reg = readl(priv->addr + parm->reg_off); 296 reg = PARM_GET(parm->width, parm->shift, reg); 297 298 debug("%s: div of %ld is %d\n", __func__, id, reg + 1); 299 300 parent_rate = meson_clk_get_rate_by_id(clk, parent); 301 if (IS_ERR_VALUE(parent_rate)) 302 return parent_rate; 303 304 debug("%s: parent rate of %ld is %d\n", __func__, id, parent_rate); 305 306 rate = parent_rate / (reg + 1); 307 308 debug("%s: rate of %ld is %d\n", __func__, id, rate); 309 310 return rate; 311 } 312 313 static ulong meson_div_set_rate(struct clk *clk, unsigned long id, ulong rate, 314 ulong current_rate) 315 { 316 struct meson_clk *priv = dev_get_priv(clk->dev); 317 unsigned int new_div = -EINVAL; 318 unsigned long parent_rate; 319 struct parm *parm; 320 int parent; 321 u32 reg; 322 int ret; 323 324 if (current_rate == rate) 325 return 0; 326 327 debug("%s: setting rate of %ld from %ld to %ld\n", 328 __func__, id, current_rate, rate); 329 330 switch (id) { 331 case CLKID_VPU_0_DIV: 332 parm = &meson_vpu_0_div_parm; 333 parent = meson_vpu_0_div_parent; 334 break; 335 case CLKID_VPU_1_DIV: 336 parm = &meson_vpu_1_div_parm; 337 parent = meson_vpu_1_div_parent; 338 break; 339 case CLKID_VAPB_0_DIV: 340 parm = &meson_vapb_0_div_parm; 341 parent = meson_vapb_0_div_parent; 342 break; 343 case CLKID_VAPB_1_DIV: 344 parm = &meson_vapb_1_div_parm; 345 parent = meson_vapb_1_div_parent; 346 break; 347 default: 348 return -ENOENT; 349 } 350 351 parent_rate = meson_clk_get_rate_by_id(clk, parent); 352 if (IS_ERR_VALUE(parent_rate)) 353 return parent_rate; 354 355 debug("%s: parent rate of %ld is %ld\n", __func__, id, parent_rate); 356 357 /* If can't divide, set parent instead */ 358 if (!parent_rate || rate > parent_rate) 359 return meson_clk_set_rate_by_id(clk, parent, rate, 360 current_rate); 361 362 new_div = DIV_ROUND_CLOSEST(parent_rate, rate); 363 364 debug("%s: new div of %ld is %d\n", __func__, id, new_div); 365 366 /* If overflow, try to set parent rate and retry */ 367 if (!new_div || new_div > (1 << parm->width)) { 368 ret = meson_clk_set_rate_by_id(clk, parent, rate, current_rate); 369 if (IS_ERR_VALUE(ret)) 370 return ret; 371 372 parent_rate = meson_clk_get_rate_by_id(clk, parent); 373 if (IS_ERR_VALUE(parent_rate)) 374 return parent_rate; 375 376 new_div = DIV_ROUND_CLOSEST(parent_rate, rate); 377 378 debug("%s: new new div of %ld is %d\n", __func__, id, new_div); 379 380 if (!new_div || new_div > (1 << parm->width)) 381 return -EINVAL; 382 } 383 384 debug("%s: setting div of %ld to %d\n", __func__, id, new_div); 385 386 reg = readl(priv->addr + parm->reg_off); 387 writel(PARM_SET(parm->width, parm->shift, reg, new_div - 1), 388 priv->addr + parm->reg_off); 389 390 debug("%s: new rate of %ld is %ld\n", 391 __func__, id, meson_div_get_rate(clk, id)); 392 393 return 0; 394 } 395 396 static struct parm meson_vpu_mux_parm = { 397 HHI_VPU_CLK_CNTL, 31, 1, 398 }; 399 400 int meson_vpu_mux_parents[] = { 401 CLKID_VPU_0, 402 CLKID_VPU_1, 403 }; 404 405 static struct parm meson_vpu_0_mux_parm = { 406 HHI_VPU_CLK_CNTL, 9, 2, 407 }; 408 409 static struct parm meson_vpu_1_mux_parm = { 410 HHI_VPU_CLK_CNTL, 25, 2, 411 }; 412 413 static int meson_vpu_0_1_mux_parents[] = { 414 CLKID_FCLK_DIV4, 415 CLKID_FCLK_DIV3, 416 CLKID_FCLK_DIV5, 417 CLKID_FCLK_DIV7, 418 }; 419 420 static struct parm meson_vapb_sel_mux_parm = { 421 HHI_VAPBCLK_CNTL, 31, 1, 422 }; 423 424 int meson_vapb_sel_mux_parents[] = { 425 CLKID_VAPB_0, 426 CLKID_VAPB_1, 427 }; 428 429 static struct parm meson_vapb_0_mux_parm = { 430 HHI_VAPBCLK_CNTL, 9, 2, 431 }; 432 433 static struct parm meson_vapb_1_mux_parm = { 434 HHI_VAPBCLK_CNTL, 25, 2, 435 }; 436 437 static int meson_vapb_0_1_mux_parents[] = { 438 CLKID_FCLK_DIV4, 439 CLKID_FCLK_DIV3, 440 CLKID_FCLK_DIV5, 441 CLKID_FCLK_DIV7, 442 }; 443 444 static ulong meson_mux_get_parent(struct clk *clk, unsigned long id) 445 { 446 struct meson_clk *priv = dev_get_priv(clk->dev); 447 struct parm *parm; 448 int *parents; 449 u32 reg; 450 451 switch (id) { 452 case CLKID_VPU: 453 parm = &meson_vpu_mux_parm; 454 parents = meson_vpu_mux_parents; 455 break; 456 case CLKID_VPU_0_SEL: 457 parm = &meson_vpu_0_mux_parm; 458 parents = meson_vpu_0_1_mux_parents; 459 break; 460 case CLKID_VPU_1_SEL: 461 parm = &meson_vpu_1_mux_parm; 462 parents = meson_vpu_0_1_mux_parents; 463 break; 464 case CLKID_VAPB_SEL: 465 parm = &meson_vapb_sel_mux_parm; 466 parents = meson_vapb_sel_mux_parents; 467 break; 468 case CLKID_VAPB_0_SEL: 469 parm = &meson_vapb_0_mux_parm; 470 parents = meson_vapb_0_1_mux_parents; 471 break; 472 case CLKID_VAPB_1_SEL: 473 parm = &meson_vapb_1_mux_parm; 474 parents = meson_vapb_0_1_mux_parents; 475 break; 476 default: 477 return -ENOENT; 478 } 479 480 reg = readl(priv->addr + parm->reg_off); 481 reg = PARM_GET(parm->width, parm->shift, reg); 482 483 debug("%s: parent of %ld is %d (%d)\n", 484 __func__, id, parents[reg], reg); 485 486 return parents[reg]; 487 } 488 489 static ulong meson_mux_set_parent(struct clk *clk, unsigned long id, 490 unsigned long parent_id) 491 { 492 unsigned long cur_parent = meson_mux_get_parent(clk, id); 493 struct meson_clk *priv = dev_get_priv(clk->dev); 494 unsigned int new_index = -EINVAL; 495 struct parm *parm; 496 int *parents; 497 u32 reg; 498 int i; 499 500 if (IS_ERR_VALUE(cur_parent)) 501 return cur_parent; 502 503 debug("%s: setting parent of %ld from %ld to %ld\n", 504 __func__, id, cur_parent, parent_id); 505 506 if (cur_parent == parent_id) 507 return 0; 508 509 switch (id) { 510 case CLKID_VPU: 511 parm = &meson_vpu_mux_parm; 512 parents = meson_vpu_mux_parents; 513 break; 514 case CLKID_VPU_0_SEL: 515 parm = &meson_vpu_0_mux_parm; 516 parents = meson_vpu_0_1_mux_parents; 517 break; 518 case CLKID_VPU_1_SEL: 519 parm = &meson_vpu_1_mux_parm; 520 parents = meson_vpu_0_1_mux_parents; 521 break; 522 case CLKID_VAPB_SEL: 523 parm = &meson_vapb_sel_mux_parm; 524 parents = meson_vapb_sel_mux_parents; 525 break; 526 case CLKID_VAPB_0_SEL: 527 parm = &meson_vapb_0_mux_parm; 528 parents = meson_vapb_0_1_mux_parents; 529 break; 530 case CLKID_VAPB_1_SEL: 531 parm = &meson_vapb_1_mux_parm; 532 parents = meson_vapb_0_1_mux_parents; 533 break; 534 default: 535 /* Not a mux */ 536 return -ENOENT; 537 } 538 539 for (i = 0 ; i < (1 << parm->width) ; ++i) { 540 if (parents[i] == parent_id) 541 new_index = i; 542 } 543 544 if (IS_ERR_VALUE(new_index)) 545 return new_index; 546 547 debug("%s: new index of %ld is %d\n", __func__, id, new_index); 548 549 reg = readl(priv->addr + parm->reg_off); 550 writel(PARM_SET(parm->width, parm->shift, reg, new_index), 551 priv->addr + parm->reg_off); 552 553 debug("%s: new parent of %ld is %ld\n", 554 __func__, id, meson_mux_get_parent(clk, id)); 555 556 return 0; 557 } 558 559 static ulong meson_mux_get_rate(struct clk *clk, unsigned long id) 560 { 561 int parent = meson_mux_get_parent(clk, id); 562 563 if (IS_ERR_VALUE(parent)) 564 return parent; 565 566 return meson_clk_get_rate_by_id(clk, parent); 567 } 568 569 static unsigned long meson_clk81_get_rate(struct clk *clk) 570 { 571 struct meson_clk *priv = dev_get_priv(clk->dev); 572 unsigned long parent_rate; 573 u32 reg; 574 int parents[] = { 575 -1, 576 -1, 577 CLKID_FCLK_DIV7, 578 CLKID_MPLL1, 579 CLKID_MPLL2, 580 CLKID_FCLK_DIV4, 581 CLKID_FCLK_DIV3, 582 CLKID_FCLK_DIV5 583 }; 584 585 /* mux */ 586 reg = readl(priv->addr + HHI_MPEG_CLK_CNTL); 587 reg = (reg >> 12) & 7; 588 589 switch (reg) { 590 case 0: 591 parent_rate = XTAL_RATE; 592 break; 593 case 1: 594 return -ENOENT; 595 default: 596 parent_rate = meson_clk_get_rate_by_id(clk, parents[reg]); 597 } 598 599 /* divider */ 600 reg = readl(priv->addr + HHI_MPEG_CLK_CNTL); 601 reg = reg & ((1 << 7) - 1); 602 603 return parent_rate / reg; 604 } 605 606 static long mpll_rate_from_params(unsigned long parent_rate, 607 unsigned long sdm, 608 unsigned long n2) 609 { 610 unsigned long divisor = (SDM_DEN * n2) + sdm; 611 612 if (n2 < N2_MIN) 613 return -EINVAL; 614 615 return DIV_ROUND_UP_ULL((u64)parent_rate * SDM_DEN, divisor); 616 } 617 618 static struct parm meson_mpll0_parm[3] = { 619 {HHI_MPLL_CNTL7, 0, 14}, /* psdm */ 620 {HHI_MPLL_CNTL7, 16, 9}, /* pn2 */ 621 }; 622 623 static struct parm meson_mpll1_parm[3] = { 624 {HHI_MPLL_CNTL8, 0, 14}, /* psdm */ 625 {HHI_MPLL_CNTL8, 16, 9}, /* pn2 */ 626 }; 627 628 static struct parm meson_mpll2_parm[3] = { 629 {HHI_MPLL_CNTL9, 0, 14}, /* psdm */ 630 {HHI_MPLL_CNTL9, 16, 9}, /* pn2 */ 631 }; 632 633 /* 634 * MultiPhase Locked Loops are outputs from a PLL with additional frequency 635 * scaling capabilities. MPLL rates are calculated as: 636 * 637 * f(N2_integer, SDM_IN ) = 2.0G/(N2_integer + SDM_IN/16384) 638 */ 639 static ulong meson_mpll_get_rate(struct clk *clk, unsigned long id) 640 { 641 struct meson_clk *priv = dev_get_priv(clk->dev); 642 struct parm *psdm, *pn2; 643 unsigned long reg, sdm, n2; 644 unsigned long parent_rate; 645 646 switch (id) { 647 case CLKID_MPLL0: 648 psdm = &meson_mpll0_parm[0]; 649 pn2 = &meson_mpll0_parm[1]; 650 break; 651 case CLKID_MPLL1: 652 psdm = &meson_mpll1_parm[0]; 653 pn2 = &meson_mpll1_parm[1]; 654 break; 655 case CLKID_MPLL2: 656 psdm = &meson_mpll2_parm[0]; 657 pn2 = &meson_mpll2_parm[1]; 658 break; 659 default: 660 return -ENOENT; 661 } 662 663 parent_rate = meson_clk_get_rate_by_id(clk, CLKID_FIXED_PLL); 664 if (IS_ERR_VALUE(parent_rate)) 665 return parent_rate; 666 667 reg = readl(priv->addr + psdm->reg_off); 668 sdm = PARM_GET(psdm->width, psdm->shift, reg); 669 670 reg = readl(priv->addr + pn2->reg_off); 671 n2 = PARM_GET(pn2->width, pn2->shift, reg); 672 673 return mpll_rate_from_params(parent_rate, sdm, n2); 674 } 675 676 static struct parm meson_fixed_pll_parm[3] = { 677 {HHI_MPLL_CNTL, 0, 9}, /* pm */ 678 {HHI_MPLL_CNTL, 9, 5}, /* pn */ 679 {HHI_MPLL_CNTL, 16, 2}, /* pod */ 680 }; 681 682 static struct parm meson_sys_pll_parm[3] = { 683 {HHI_SYS_PLL_CNTL, 0, 9}, /* pm */ 684 {HHI_SYS_PLL_CNTL, 9, 5}, /* pn */ 685 {HHI_SYS_PLL_CNTL, 10, 2}, /* pod */ 686 }; 687 688 static ulong meson_pll_get_rate(struct clk *clk, unsigned long id) 689 { 690 struct meson_clk *priv = dev_get_priv(clk->dev); 691 struct parm *pm, *pn, *pod; 692 unsigned long parent_rate_mhz = XTAL_RATE / 1000000; 693 u16 n, m, od; 694 u32 reg; 695 696 switch (id) { 697 case CLKID_FIXED_PLL: 698 pm = &meson_fixed_pll_parm[0]; 699 pn = &meson_fixed_pll_parm[1]; 700 pod = &meson_fixed_pll_parm[2]; 701 break; 702 case CLKID_SYS_PLL: 703 pm = &meson_sys_pll_parm[0]; 704 pn = &meson_sys_pll_parm[1]; 705 pod = &meson_sys_pll_parm[2]; 706 break; 707 default: 708 return -ENOENT; 709 } 710 711 reg = readl(priv->addr + pn->reg_off); 712 n = PARM_GET(pn->width, pn->shift, reg); 713 714 reg = readl(priv->addr + pm->reg_off); 715 m = PARM_GET(pm->width, pm->shift, reg); 716 717 reg = readl(priv->addr + pod->reg_off); 718 od = PARM_GET(pod->width, pod->shift, reg); 719 720 return ((parent_rate_mhz * m / n) >> od) * 1000000; 721 } 722 723 static ulong meson_clk_get_rate_by_id(struct clk *clk, unsigned long id) 724 { 725 ulong rate; 726 727 switch (id) { 728 case CLKID_FIXED_PLL: 729 case CLKID_SYS_PLL: 730 rate = meson_pll_get_rate(clk, id); 731 break; 732 case CLKID_FCLK_DIV2: 733 rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 2; 734 break; 735 case CLKID_FCLK_DIV3: 736 rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 3; 737 break; 738 case CLKID_FCLK_DIV4: 739 rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 4; 740 break; 741 case CLKID_FCLK_DIV5: 742 rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 5; 743 break; 744 case CLKID_FCLK_DIV7: 745 rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 7; 746 break; 747 case CLKID_MPLL0: 748 case CLKID_MPLL1: 749 case CLKID_MPLL2: 750 rate = meson_mpll_get_rate(clk, id); 751 break; 752 case CLKID_CLK81: 753 rate = meson_clk81_get_rate(clk); 754 break; 755 case CLKID_VPU_0: 756 rate = meson_div_get_rate(clk, CLKID_VPU_0_DIV); 757 break; 758 case CLKID_VPU_1: 759 rate = meson_div_get_rate(clk, CLKID_VPU_1_DIV); 760 break; 761 case CLKID_VAPB: 762 rate = meson_mux_get_rate(clk, CLKID_VAPB_SEL); 763 break; 764 case CLKID_VAPB_0: 765 rate = meson_div_get_rate(clk, CLKID_VAPB_0_DIV); 766 break; 767 case CLKID_VAPB_1: 768 rate = meson_div_get_rate(clk, CLKID_VAPB_1_DIV); 769 break; 770 case CLKID_VPU_0_DIV: 771 case CLKID_VPU_1_DIV: 772 case CLKID_VAPB_0_DIV: 773 case CLKID_VAPB_1_DIV: 774 rate = meson_div_get_rate(clk, id); 775 break; 776 case CLKID_VPU: 777 case CLKID_VPU_0_SEL: 778 case CLKID_VPU_1_SEL: 779 case CLKID_VAPB_SEL: 780 case CLKID_VAPB_0_SEL: 781 case CLKID_VAPB_1_SEL: 782 rate = meson_mux_get_rate(clk, id); 783 break; 784 default: 785 if (gates[id].reg != 0) { 786 /* a clock gate */ 787 rate = meson_clk81_get_rate(clk); 788 break; 789 } 790 return -ENOENT; 791 } 792 793 printf("clock %lu has rate %lu\n", id, rate); 794 return rate; 795 } 796 797 static ulong meson_clk_get_rate(struct clk *clk) 798 { 799 return meson_clk_get_rate_by_id(clk, clk->id); 800 } 801 802 static int meson_clk_set_parent(struct clk *clk, struct clk *parent) 803 { 804 return meson_mux_set_parent(clk, clk->id, parent->id); 805 } 806 807 static ulong meson_clk_set_rate_by_id(struct clk *clk, unsigned long id, 808 ulong rate, ulong current_rate) 809 { 810 if (current_rate == rate) 811 return 0; 812 813 switch (id) { 814 /* Fixed clocks */ 815 case CLKID_FIXED_PLL: 816 case CLKID_SYS_PLL: 817 case CLKID_FCLK_DIV2: 818 case CLKID_FCLK_DIV3: 819 case CLKID_FCLK_DIV4: 820 case CLKID_FCLK_DIV5: 821 case CLKID_FCLK_DIV7: 822 case CLKID_MPLL0: 823 case CLKID_MPLL1: 824 case CLKID_MPLL2: 825 case CLKID_CLK81: 826 if (current_rate != rate) 827 return -EINVAL; 828 829 return 0; 830 case CLKID_VPU: 831 return meson_clk_set_rate_by_id(clk, 832 meson_mux_get_parent(clk, CLKID_VPU), rate, 833 current_rate); 834 case CLKID_VAPB: 835 case CLKID_VAPB_SEL: 836 return meson_clk_set_rate_by_id(clk, 837 meson_mux_get_parent(clk, CLKID_VAPB_SEL), 838 rate, current_rate); 839 case CLKID_VPU_0: 840 return meson_div_set_rate(clk, CLKID_VPU_0_DIV, rate, 841 current_rate); 842 case CLKID_VPU_1: 843 return meson_div_set_rate(clk, CLKID_VPU_1_DIV, rate, 844 current_rate); 845 case CLKID_VAPB_0: 846 return meson_div_set_rate(clk, CLKID_VAPB_0_DIV, rate, 847 current_rate); 848 case CLKID_VAPB_1: 849 return meson_div_set_rate(clk, CLKID_VAPB_1_DIV, rate, 850 current_rate); 851 case CLKID_VPU_0_DIV: 852 case CLKID_VPU_1_DIV: 853 case CLKID_VAPB_0_DIV: 854 case CLKID_VAPB_1_DIV: 855 return meson_div_set_rate(clk, id, rate, current_rate); 856 default: 857 return -ENOENT; 858 } 859 860 return -EINVAL; 861 } 862 863 static ulong meson_clk_set_rate(struct clk *clk, ulong rate) 864 { 865 ulong current_rate = meson_clk_get_rate_by_id(clk, clk->id); 866 int ret; 867 868 if (IS_ERR_VALUE(current_rate)) 869 return current_rate; 870 871 debug("%s: setting rate of %ld from %ld to %ld\n", 872 __func__, clk->id, current_rate, rate); 873 874 ret = meson_clk_set_rate_by_id(clk, clk->id, rate, current_rate); 875 if (IS_ERR_VALUE(ret)) 876 return ret; 877 878 printf("clock %lu has new rate %lu\n", clk->id, 879 meson_clk_get_rate_by_id(clk, clk->id)); 880 881 return 0; 882 } 883 884 static int meson_clk_probe(struct udevice *dev) 885 { 886 struct meson_clk *priv = dev_get_priv(dev); 887 888 priv->addr = dev_read_addr_ptr(dev); 889 890 debug("meson-clk: probed at addr %p\n", priv->addr); 891 892 return 0; 893 } 894 895 static struct clk_ops meson_clk_ops = { 896 .disable = meson_clk_disable, 897 .enable = meson_clk_enable, 898 .get_rate = meson_clk_get_rate, 899 .set_parent = meson_clk_set_parent, 900 .set_rate = meson_clk_set_rate, 901 }; 902 903 static const struct udevice_id meson_clk_ids[] = { 904 { .compatible = "amlogic,gxbb-clkc" }, 905 { .compatible = "amlogic,gxl-clkc" }, 906 { } 907 }; 908 909 U_BOOT_DRIVER(meson_clk) = { 910 .name = "meson_clk", 911 .id = UCLASS_CLK, 912 .of_match = meson_clk_ids, 913 .priv_auto_alloc_size = sizeof(struct meson_clk), 914 .ops = &meson_clk_ops, 915 .probe = meson_clk_probe, 916 }; 917