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-gx.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 static 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 /* clk81 divider is zero based */ 604 return parent_rate / (reg + 1); 605 } 606 607 static long mpll_rate_from_params(unsigned long parent_rate, 608 unsigned long sdm, 609 unsigned long n2) 610 { 611 unsigned long divisor = (SDM_DEN * n2) + sdm; 612 613 if (n2 < N2_MIN) 614 return -EINVAL; 615 616 return DIV_ROUND_UP_ULL((u64)parent_rate * SDM_DEN, divisor); 617 } 618 619 static struct parm meson_mpll0_parm[3] = { 620 {HHI_MPLL_CNTL7, 0, 14}, /* psdm */ 621 {HHI_MPLL_CNTL7, 16, 9}, /* pn2 */ 622 }; 623 624 static struct parm meson_mpll1_parm[3] = { 625 {HHI_MPLL_CNTL8, 0, 14}, /* psdm */ 626 {HHI_MPLL_CNTL8, 16, 9}, /* pn2 */ 627 }; 628 629 static struct parm meson_mpll2_parm[3] = { 630 {HHI_MPLL_CNTL9, 0, 14}, /* psdm */ 631 {HHI_MPLL_CNTL9, 16, 9}, /* pn2 */ 632 }; 633 634 /* 635 * MultiPhase Locked Loops are outputs from a PLL with additional frequency 636 * scaling capabilities. MPLL rates are calculated as: 637 * 638 * f(N2_integer, SDM_IN ) = 2.0G/(N2_integer + SDM_IN/16384) 639 */ 640 static ulong meson_mpll_get_rate(struct clk *clk, unsigned long id) 641 { 642 struct meson_clk *priv = dev_get_priv(clk->dev); 643 struct parm *psdm, *pn2; 644 unsigned long reg, sdm, n2; 645 unsigned long parent_rate; 646 647 switch (id) { 648 case CLKID_MPLL0: 649 psdm = &meson_mpll0_parm[0]; 650 pn2 = &meson_mpll0_parm[1]; 651 break; 652 case CLKID_MPLL1: 653 psdm = &meson_mpll1_parm[0]; 654 pn2 = &meson_mpll1_parm[1]; 655 break; 656 case CLKID_MPLL2: 657 psdm = &meson_mpll2_parm[0]; 658 pn2 = &meson_mpll2_parm[1]; 659 break; 660 default: 661 return -ENOENT; 662 } 663 664 parent_rate = meson_clk_get_rate_by_id(clk, CLKID_FIXED_PLL); 665 if (IS_ERR_VALUE(parent_rate)) 666 return parent_rate; 667 668 reg = readl(priv->addr + psdm->reg_off); 669 sdm = PARM_GET(psdm->width, psdm->shift, reg); 670 671 reg = readl(priv->addr + pn2->reg_off); 672 n2 = PARM_GET(pn2->width, pn2->shift, reg); 673 674 return mpll_rate_from_params(parent_rate, sdm, n2); 675 } 676 677 static struct parm meson_fixed_pll_parm[3] = { 678 {HHI_MPLL_CNTL, 0, 9}, /* pm */ 679 {HHI_MPLL_CNTL, 9, 5}, /* pn */ 680 {HHI_MPLL_CNTL, 16, 2}, /* pod */ 681 }; 682 683 static struct parm meson_sys_pll_parm[3] = { 684 {HHI_SYS_PLL_CNTL, 0, 9}, /* pm */ 685 {HHI_SYS_PLL_CNTL, 9, 5}, /* pn */ 686 {HHI_SYS_PLL_CNTL, 10, 2}, /* pod */ 687 }; 688 689 static ulong meson_pll_get_rate(struct clk *clk, unsigned long id) 690 { 691 struct meson_clk *priv = dev_get_priv(clk->dev); 692 struct parm *pm, *pn, *pod; 693 unsigned long parent_rate_mhz = XTAL_RATE / 1000000; 694 u16 n, m, od; 695 u32 reg; 696 697 switch (id) { 698 case CLKID_FIXED_PLL: 699 pm = &meson_fixed_pll_parm[0]; 700 pn = &meson_fixed_pll_parm[1]; 701 pod = &meson_fixed_pll_parm[2]; 702 break; 703 case CLKID_SYS_PLL: 704 pm = &meson_sys_pll_parm[0]; 705 pn = &meson_sys_pll_parm[1]; 706 pod = &meson_sys_pll_parm[2]; 707 break; 708 default: 709 return -ENOENT; 710 } 711 712 reg = readl(priv->addr + pn->reg_off); 713 n = PARM_GET(pn->width, pn->shift, reg); 714 715 reg = readl(priv->addr + pm->reg_off); 716 m = PARM_GET(pm->width, pm->shift, reg); 717 718 reg = readl(priv->addr + pod->reg_off); 719 od = PARM_GET(pod->width, pod->shift, reg); 720 721 return ((parent_rate_mhz * m / n) >> od) * 1000000; 722 } 723 724 static ulong meson_clk_get_rate_by_id(struct clk *clk, unsigned long id) 725 { 726 ulong rate; 727 728 switch (id) { 729 case CLKID_FIXED_PLL: 730 case CLKID_SYS_PLL: 731 rate = meson_pll_get_rate(clk, id); 732 break; 733 case CLKID_FCLK_DIV2: 734 rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 2; 735 break; 736 case CLKID_FCLK_DIV3: 737 rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 3; 738 break; 739 case CLKID_FCLK_DIV4: 740 rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 4; 741 break; 742 case CLKID_FCLK_DIV5: 743 rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 5; 744 break; 745 case CLKID_FCLK_DIV7: 746 rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 7; 747 break; 748 case CLKID_MPLL0: 749 case CLKID_MPLL1: 750 case CLKID_MPLL2: 751 rate = meson_mpll_get_rate(clk, id); 752 break; 753 case CLKID_CLK81: 754 rate = meson_clk81_get_rate(clk); 755 break; 756 case CLKID_VPU_0: 757 rate = meson_div_get_rate(clk, CLKID_VPU_0_DIV); 758 break; 759 case CLKID_VPU_1: 760 rate = meson_div_get_rate(clk, CLKID_VPU_1_DIV); 761 break; 762 case CLKID_VAPB: 763 rate = meson_mux_get_rate(clk, CLKID_VAPB_SEL); 764 break; 765 case CLKID_VAPB_0: 766 rate = meson_div_get_rate(clk, CLKID_VAPB_0_DIV); 767 break; 768 case CLKID_VAPB_1: 769 rate = meson_div_get_rate(clk, CLKID_VAPB_1_DIV); 770 break; 771 case CLKID_VPU_0_DIV: 772 case CLKID_VPU_1_DIV: 773 case CLKID_VAPB_0_DIV: 774 case CLKID_VAPB_1_DIV: 775 rate = meson_div_get_rate(clk, id); 776 break; 777 case CLKID_VPU: 778 case CLKID_VPU_0_SEL: 779 case CLKID_VPU_1_SEL: 780 case CLKID_VAPB_SEL: 781 case CLKID_VAPB_0_SEL: 782 case CLKID_VAPB_1_SEL: 783 rate = meson_mux_get_rate(clk, id); 784 break; 785 default: 786 if (gates[id].reg != 0) { 787 /* a clock gate */ 788 rate = meson_clk81_get_rate(clk); 789 break; 790 } 791 return -ENOENT; 792 } 793 794 debug("clock %lu has rate %lu\n", id, rate); 795 return rate; 796 } 797 798 static ulong meson_clk_get_rate(struct clk *clk) 799 { 800 return meson_clk_get_rate_by_id(clk, clk->id); 801 } 802 803 static int meson_clk_set_parent(struct clk *clk, struct clk *parent) 804 { 805 return meson_mux_set_parent(clk, clk->id, parent->id); 806 } 807 808 static ulong meson_clk_set_rate_by_id(struct clk *clk, unsigned long id, 809 ulong rate, ulong current_rate) 810 { 811 if (current_rate == rate) 812 return 0; 813 814 switch (id) { 815 /* Fixed clocks */ 816 case CLKID_FIXED_PLL: 817 case CLKID_SYS_PLL: 818 case CLKID_FCLK_DIV2: 819 case CLKID_FCLK_DIV3: 820 case CLKID_FCLK_DIV4: 821 case CLKID_FCLK_DIV5: 822 case CLKID_FCLK_DIV7: 823 case CLKID_MPLL0: 824 case CLKID_MPLL1: 825 case CLKID_MPLL2: 826 case CLKID_CLK81: 827 if (current_rate != rate) 828 return -EINVAL; 829 830 return 0; 831 case CLKID_VPU: 832 return meson_clk_set_rate_by_id(clk, 833 meson_mux_get_parent(clk, CLKID_VPU), rate, 834 current_rate); 835 case CLKID_VAPB: 836 case CLKID_VAPB_SEL: 837 return meson_clk_set_rate_by_id(clk, 838 meson_mux_get_parent(clk, CLKID_VAPB_SEL), 839 rate, current_rate); 840 case CLKID_VPU_0: 841 return meson_div_set_rate(clk, CLKID_VPU_0_DIV, rate, 842 current_rate); 843 case CLKID_VPU_1: 844 return meson_div_set_rate(clk, CLKID_VPU_1_DIV, rate, 845 current_rate); 846 case CLKID_VAPB_0: 847 return meson_div_set_rate(clk, CLKID_VAPB_0_DIV, rate, 848 current_rate); 849 case CLKID_VAPB_1: 850 return meson_div_set_rate(clk, CLKID_VAPB_1_DIV, rate, 851 current_rate); 852 case CLKID_VPU_0_DIV: 853 case CLKID_VPU_1_DIV: 854 case CLKID_VAPB_0_DIV: 855 case CLKID_VAPB_1_DIV: 856 return meson_div_set_rate(clk, id, rate, current_rate); 857 default: 858 return -ENOENT; 859 } 860 861 return -EINVAL; 862 } 863 864 static ulong meson_clk_set_rate(struct clk *clk, ulong rate) 865 { 866 ulong current_rate = meson_clk_get_rate_by_id(clk, clk->id); 867 int ret; 868 869 if (IS_ERR_VALUE(current_rate)) 870 return current_rate; 871 872 debug("%s: setting rate of %ld from %ld to %ld\n", 873 __func__, clk->id, current_rate, rate); 874 875 ret = meson_clk_set_rate_by_id(clk, clk->id, rate, current_rate); 876 if (IS_ERR_VALUE(ret)) 877 return ret; 878 879 printf("clock %lu has new rate %lu\n", clk->id, 880 meson_clk_get_rate_by_id(clk, clk->id)); 881 882 return 0; 883 } 884 885 static int meson_clk_probe(struct udevice *dev) 886 { 887 struct meson_clk *priv = dev_get_priv(dev); 888 889 priv->addr = dev_read_addr_ptr(dev); 890 891 debug("meson-clk: probed at addr %p\n", priv->addr); 892 893 return 0; 894 } 895 896 static struct clk_ops meson_clk_ops = { 897 .disable = meson_clk_disable, 898 .enable = meson_clk_enable, 899 .get_rate = meson_clk_get_rate, 900 .set_parent = meson_clk_set_parent, 901 .set_rate = meson_clk_set_rate, 902 }; 903 904 static const struct udevice_id meson_clk_ids[] = { 905 { .compatible = "amlogic,gxbb-clkc" }, 906 { .compatible = "amlogic,gxl-clkc" }, 907 { } 908 }; 909 910 U_BOOT_DRIVER(meson_clk) = { 911 .name = "meson_clk", 912 .id = UCLASS_CLK, 913 .of_match = meson_clk_ids, 914 .priv_auto_alloc_size = sizeof(struct meson_clk), 915 .ops = &meson_clk_ops, 916 .probe = meson_clk_probe, 917 }; 918