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 <regmap.h> 15 #include <syscon.h> 16 #include <dt-bindings/clock/gxbb-clkc.h> 17 #include "clk_meson.h" 18 19 /* This driver support only basic clock tree operations : 20 * - Can calculate clock frequency on a limited tree 21 * - Can Read muxes and basic dividers (0-based only) 22 * - Can enable/disable gates with limited propagation 23 * - Can reparent without propagation, only on muxes 24 * - Can set rates without reparenting 25 * This driver is adapted to what is actually supported by U-Boot 26 */ 27 28 /* Only the clocks ids we don't want to expose, such as the internal muxes 29 * and dividers of composite clocks, will remain defined here. 30 */ 31 #define CLKID_MPEG_SEL 10 32 #define CLKID_MPEG_DIV 11 33 #define CLKID_SAR_ADC_DIV 99 34 #define CLKID_MALI_0_DIV 101 35 #define CLKID_MALI_1_DIV 104 36 #define CLKID_CTS_AMCLK_SEL 108 37 #define CLKID_CTS_AMCLK_DIV 109 38 #define CLKID_CTS_MCLK_I958_SEL 111 39 #define CLKID_CTS_MCLK_I958_DIV 112 40 #define CLKID_32K_CLK_SEL 115 41 #define CLKID_32K_CLK_DIV 116 42 #define CLKID_SD_EMMC_A_CLK0_SEL 117 43 #define CLKID_SD_EMMC_A_CLK0_DIV 118 44 #define CLKID_SD_EMMC_B_CLK0_SEL 120 45 #define CLKID_SD_EMMC_B_CLK0_DIV 121 46 #define CLKID_SD_EMMC_C_CLK0_SEL 123 47 #define CLKID_SD_EMMC_C_CLK0_DIV 124 48 #define CLKID_VPU_0_DIV 127 49 #define CLKID_VPU_1_DIV 130 50 #define CLKID_VAPB_0_DIV 134 51 #define CLKID_VAPB_1_DIV 137 52 #define CLKID_HDMI_PLL_PRE_MULT 141 53 #define CLKID_MPLL0_DIV 142 54 #define CLKID_MPLL1_DIV 143 55 #define CLKID_MPLL2_DIV 144 56 #define CLKID_MPLL_PREDIV 145 57 #define CLKID_FCLK_DIV2_DIV 146 58 #define CLKID_FCLK_DIV3_DIV 147 59 #define CLKID_FCLK_DIV4_DIV 148 60 #define CLKID_FCLK_DIV5_DIV 149 61 #define CLKID_FCLK_DIV7_DIV 150 62 #define CLKID_VDEC_1_SEL 151 63 #define CLKID_VDEC_1_DIV 152 64 #define CLKID_VDEC_HEVC_SEL 154 65 #define CLKID_VDEC_HEVC_DIV 155 66 67 #define XTAL_RATE 24000000 68 69 struct meson_clk { 70 struct regmap *map; 71 }; 72 73 static ulong meson_div_get_rate(struct clk *clk, unsigned long id); 74 static ulong meson_div_set_rate(struct clk *clk, unsigned long id, ulong rate, 75 ulong current_rate); 76 static ulong meson_mux_set_parent(struct clk *clk, unsigned long id, 77 unsigned long parent_id); 78 static ulong meson_mux_get_rate(struct clk *clk, unsigned long id); 79 static ulong meson_clk_set_rate_by_id(struct clk *clk, unsigned long id, 80 ulong rate, ulong current_rate); 81 static ulong meson_mux_get_parent(struct clk *clk, unsigned long id); 82 static ulong meson_clk_get_rate_by_id(struct clk *clk, unsigned long id); 83 84 static struct meson_gate gates[] = { 85 /* Everything Else (EE) domain gates */ 86 MESON_GATE(CLKID_DDR, HHI_GCLK_MPEG0, 0), 87 MESON_GATE(CLKID_DOS, HHI_GCLK_MPEG0, 1), 88 MESON_GATE(CLKID_ISA, HHI_GCLK_MPEG0, 5), 89 MESON_GATE(CLKID_PL301, HHI_GCLK_MPEG0, 6), 90 MESON_GATE(CLKID_PERIPHS, HHI_GCLK_MPEG0, 7), 91 MESON_GATE(CLKID_SPICC, HHI_GCLK_MPEG0, 8), 92 MESON_GATE(CLKID_I2C, HHI_GCLK_MPEG0, 9), 93 MESON_GATE(CLKID_SAR_ADC, HHI_GCLK_MPEG0, 10), 94 MESON_GATE(CLKID_SMART_CARD, HHI_GCLK_MPEG0, 11), 95 MESON_GATE(CLKID_RNG0, HHI_GCLK_MPEG0, 12), 96 MESON_GATE(CLKID_UART0, HHI_GCLK_MPEG0, 13), 97 MESON_GATE(CLKID_SDHC, HHI_GCLK_MPEG0, 14), 98 MESON_GATE(CLKID_STREAM, HHI_GCLK_MPEG0, 15), 99 MESON_GATE(CLKID_ASYNC_FIFO, HHI_GCLK_MPEG0, 16), 100 MESON_GATE(CLKID_SDIO, HHI_GCLK_MPEG0, 17), 101 MESON_GATE(CLKID_ABUF, HHI_GCLK_MPEG0, 18), 102 MESON_GATE(CLKID_HIU_IFACE, HHI_GCLK_MPEG0, 19), 103 MESON_GATE(CLKID_ASSIST_MISC, HHI_GCLK_MPEG0, 23), 104 MESON_GATE(CLKID_SD_EMMC_A, HHI_GCLK_MPEG0, 24), 105 MESON_GATE(CLKID_SD_EMMC_B, HHI_GCLK_MPEG0, 25), 106 MESON_GATE(CLKID_SD_EMMC_C, HHI_GCLK_MPEG0, 26), 107 MESON_GATE(CLKID_SPI, HHI_GCLK_MPEG0, 30), 108 109 MESON_GATE(CLKID_I2S_SPDIF, HHI_GCLK_MPEG1, 2), 110 MESON_GATE(CLKID_ETH, HHI_GCLK_MPEG1, 3), 111 MESON_GATE(CLKID_DEMUX, HHI_GCLK_MPEG1, 4), 112 MESON_GATE(CLKID_AIU_GLUE, HHI_GCLK_MPEG1, 6), 113 MESON_GATE(CLKID_IEC958, HHI_GCLK_MPEG1, 7), 114 MESON_GATE(CLKID_I2S_OUT, HHI_GCLK_MPEG1, 8), 115 MESON_GATE(CLKID_AMCLK, HHI_GCLK_MPEG1, 9), 116 MESON_GATE(CLKID_AIFIFO2, HHI_GCLK_MPEG1, 10), 117 MESON_GATE(CLKID_MIXER, HHI_GCLK_MPEG1, 11), 118 MESON_GATE(CLKID_MIXER_IFACE, HHI_GCLK_MPEG1, 12), 119 MESON_GATE(CLKID_ADC, HHI_GCLK_MPEG1, 13), 120 MESON_GATE(CLKID_BLKMV, HHI_GCLK_MPEG1, 14), 121 MESON_GATE(CLKID_AIU, HHI_GCLK_MPEG1, 15), 122 MESON_GATE(CLKID_UART1, HHI_GCLK_MPEG1, 16), 123 MESON_GATE(CLKID_G2D, HHI_GCLK_MPEG1, 20), 124 MESON_GATE(CLKID_USB0, HHI_GCLK_MPEG1, 21), 125 MESON_GATE(CLKID_USB1, HHI_GCLK_MPEG1, 22), 126 MESON_GATE(CLKID_RESET, HHI_GCLK_MPEG1, 23), 127 MESON_GATE(CLKID_NAND, HHI_GCLK_MPEG1, 24), 128 MESON_GATE(CLKID_DOS_PARSER, HHI_GCLK_MPEG1, 25), 129 MESON_GATE(CLKID_USB, HHI_GCLK_MPEG1, 26), 130 MESON_GATE(CLKID_VDIN1, HHI_GCLK_MPEG1, 28), 131 MESON_GATE(CLKID_AHB_ARB0, HHI_GCLK_MPEG1, 29), 132 MESON_GATE(CLKID_EFUSE, HHI_GCLK_MPEG1, 30), 133 MESON_GATE(CLKID_BOOT_ROM, HHI_GCLK_MPEG1, 31), 134 135 MESON_GATE(CLKID_AHB_DATA_BUS, HHI_GCLK_MPEG2, 1), 136 MESON_GATE(CLKID_AHB_CTRL_BUS, HHI_GCLK_MPEG2, 2), 137 MESON_GATE(CLKID_HDMI_INTR_SYNC, HHI_GCLK_MPEG2, 3), 138 MESON_GATE(CLKID_HDMI_PCLK, HHI_GCLK_MPEG2, 4), 139 MESON_GATE(CLKID_USB1_DDR_BRIDGE, HHI_GCLK_MPEG2, 8), 140 MESON_GATE(CLKID_USB0_DDR_BRIDGE, HHI_GCLK_MPEG2, 9), 141 MESON_GATE(CLKID_MMC_PCLK, HHI_GCLK_MPEG2, 11), 142 MESON_GATE(CLKID_DVIN, HHI_GCLK_MPEG2, 12), 143 MESON_GATE(CLKID_UART2, HHI_GCLK_MPEG2, 15), 144 MESON_GATE(CLKID_SANA, HHI_GCLK_MPEG2, 22), 145 MESON_GATE(CLKID_VPU_INTR, HHI_GCLK_MPEG2, 25), 146 MESON_GATE(CLKID_SEC_AHB_AHB3_BRIDGE, HHI_GCLK_MPEG2, 26), 147 MESON_GATE(CLKID_CLK81_A53, HHI_GCLK_MPEG2, 29), 148 149 MESON_GATE(CLKID_VCLK2_VENCI0, HHI_GCLK_OTHER, 1), 150 MESON_GATE(CLKID_VCLK2_VENCI1, HHI_GCLK_OTHER, 2), 151 MESON_GATE(CLKID_VCLK2_VENCP0, HHI_GCLK_OTHER, 3), 152 MESON_GATE(CLKID_VCLK2_VENCP1, HHI_GCLK_OTHER, 4), 153 MESON_GATE(CLKID_GCLK_VENCI_INT0, HHI_GCLK_OTHER, 8), 154 MESON_GATE(CLKID_DAC_CLK, HHI_GCLK_OTHER, 10), 155 MESON_GATE(CLKID_AOCLK_GATE, HHI_GCLK_OTHER, 14), 156 MESON_GATE(CLKID_IEC958_GATE, HHI_GCLK_OTHER, 16), 157 MESON_GATE(CLKID_ENC480P, HHI_GCLK_OTHER, 20), 158 MESON_GATE(CLKID_RNG1, HHI_GCLK_OTHER, 21), 159 MESON_GATE(CLKID_GCLK_VENCI_INT1, HHI_GCLK_OTHER, 22), 160 MESON_GATE(CLKID_VCLK2_VENCLMCC, HHI_GCLK_OTHER, 24), 161 MESON_GATE(CLKID_VCLK2_VENCL, HHI_GCLK_OTHER, 25), 162 MESON_GATE(CLKID_VCLK_OTHER, HHI_GCLK_OTHER, 26), 163 MESON_GATE(CLKID_EDP, HHI_GCLK_OTHER, 31), 164 165 /* Always On (AO) domain gates */ 166 MESON_GATE(CLKID_AO_MEDIA_CPU, HHI_GCLK_AO, 0), 167 MESON_GATE(CLKID_AO_AHB_SRAM, HHI_GCLK_AO, 1), 168 MESON_GATE(CLKID_AO_AHB_BUS, HHI_GCLK_AO, 2), 169 MESON_GATE(CLKID_AO_IFACE, HHI_GCLK_AO, 3), 170 MESON_GATE(CLKID_AO_I2C, HHI_GCLK_AO, 4), 171 172 /* PLL Gates */ 173 /* CLKID_FCLK_DIV2 is critical for the SCPI Processor */ 174 MESON_GATE(CLKID_FCLK_DIV3, HHI_MPLL_CNTL6, 28), 175 MESON_GATE(CLKID_FCLK_DIV4, HHI_MPLL_CNTL6, 29), 176 MESON_GATE(CLKID_FCLK_DIV5, HHI_MPLL_CNTL6, 30), 177 MESON_GATE(CLKID_FCLK_DIV7, HHI_MPLL_CNTL6, 31), 178 MESON_GATE(CLKID_MPLL0, HHI_MPLL_CNTL7, 14), 179 MESON_GATE(CLKID_MPLL1, HHI_MPLL_CNTL8, 14), 180 MESON_GATE(CLKID_MPLL2, HHI_MPLL_CNTL9, 14), 181 /* CLKID_CLK81 is critical for the system */ 182 183 /* Peripheral Gates */ 184 MESON_GATE(CLKID_SAR_ADC_CLK, HHI_SAR_CLK_CNTL, 8), 185 MESON_GATE(CLKID_SD_EMMC_A_CLK0, HHI_SD_EMMC_CLK_CNTL, 7), 186 MESON_GATE(CLKID_SD_EMMC_B_CLK0, HHI_SD_EMMC_CLK_CNTL, 23), 187 MESON_GATE(CLKID_SD_EMMC_C_CLK0, HHI_NAND_CLK_CNTL, 7), 188 MESON_GATE(CLKID_VPU_0, HHI_VPU_CLK_CNTL, 8), 189 MESON_GATE(CLKID_VPU_1, HHI_VPU_CLK_CNTL, 24), 190 MESON_GATE(CLKID_VAPB_0, HHI_VAPBCLK_CNTL, 8), 191 MESON_GATE(CLKID_VAPB_1, HHI_VAPBCLK_CNTL, 24), 192 MESON_GATE(CLKID_VAPB, HHI_VAPBCLK_CNTL, 30), 193 }; 194 195 static int meson_set_gate_by_id(struct clk *clk, unsigned long id, bool on) 196 { 197 struct meson_clk *priv = dev_get_priv(clk->dev); 198 struct meson_gate *gate; 199 200 debug("%s: %sabling %ld\n", __func__, on ? "en" : "dis", id); 201 202 /* Propagate through muxes */ 203 switch (id) { 204 case CLKID_VPU: 205 return meson_set_gate_by_id(clk, 206 meson_mux_get_parent(clk, CLKID_VPU), on); 207 case CLKID_VAPB_SEL: 208 return meson_set_gate_by_id(clk, 209 meson_mux_get_parent(clk, CLKID_VAPB_SEL), on); 210 } 211 212 if (id >= ARRAY_SIZE(gates)) 213 return -ENOENT; 214 215 gate = &gates[id]; 216 217 if (gate->reg == 0) 218 return 0; 219 220 debug("%s: really %sabling %ld\n", __func__, on ? "en" : "dis", id); 221 222 regmap_update_bits(priv->map, gate->reg, 223 BIT(gate->bit), on ? BIT(gate->bit) : 0); 224 225 /* Propagate to next gate(s) */ 226 switch (id) { 227 case CLKID_VAPB: 228 return meson_set_gate_by_id(clk, CLKID_VAPB_SEL, on); 229 } 230 231 return 0; 232 } 233 234 static int meson_clk_enable(struct clk *clk) 235 { 236 return meson_set_gate_by_id(clk, clk->id, true); 237 } 238 239 static int meson_clk_disable(struct clk *clk) 240 { 241 return meson_set_gate_by_id(clk, clk->id, false); 242 } 243 244 static struct parm meson_vpu_0_div_parm = { 245 HHI_VPU_CLK_CNTL, 0, 7, 246 }; 247 248 int meson_vpu_0_div_parent = CLKID_VPU_0_SEL; 249 250 static struct parm meson_vpu_1_div_parm = { 251 HHI_VPU_CLK_CNTL, 16, 7, 252 }; 253 254 int meson_vpu_1_div_parent = CLKID_VPU_1_SEL; 255 256 static struct parm meson_vapb_0_div_parm = { 257 HHI_VAPBCLK_CNTL, 0, 7, 258 }; 259 260 int meson_vapb_0_div_parent = CLKID_VAPB_0_SEL; 261 262 static struct parm meson_vapb_1_div_parm = { 263 HHI_VAPBCLK_CNTL, 16, 7, 264 }; 265 266 int meson_vapb_1_div_parent = CLKID_VAPB_1_SEL; 267 268 static ulong meson_div_get_rate(struct clk *clk, unsigned long id) 269 { 270 struct meson_clk *priv = dev_get_priv(clk->dev); 271 unsigned int rate, parent_rate; 272 struct parm *parm; 273 int parent; 274 uint reg; 275 276 switch (id) { 277 case CLKID_VPU_0_DIV: 278 parm = &meson_vpu_0_div_parm; 279 parent = meson_vpu_0_div_parent; 280 break; 281 case CLKID_VPU_1_DIV: 282 parm = &meson_vpu_1_div_parm; 283 parent = meson_vpu_1_div_parent; 284 break; 285 case CLKID_VAPB_0_DIV: 286 parm = &meson_vapb_0_div_parm; 287 parent = meson_vapb_0_div_parent; 288 break; 289 case CLKID_VAPB_1_DIV: 290 parm = &meson_vapb_1_div_parm; 291 parent = meson_vapb_1_div_parent; 292 break; 293 default: 294 return -ENOENT; 295 } 296 297 regmap_read(priv->map, parm->reg_off, ®); 298 reg = PARM_GET(parm->width, parm->shift, reg); 299 300 debug("%s: div of %ld is %d\n", __func__, id, reg + 1); 301 302 parent_rate = meson_clk_get_rate_by_id(clk, parent); 303 if (IS_ERR_VALUE(parent_rate)) 304 return parent_rate; 305 306 debug("%s: parent rate of %ld is %d\n", __func__, id, parent_rate); 307 308 rate = parent_rate / (reg + 1); 309 310 debug("%s: rate of %ld is %d\n", __func__, id, rate); 311 312 return rate; 313 } 314 315 static ulong meson_div_set_rate(struct clk *clk, unsigned long id, ulong rate, 316 ulong current_rate) 317 { 318 struct meson_clk *priv = dev_get_priv(clk->dev); 319 unsigned int new_div = -EINVAL; 320 unsigned long parent_rate; 321 struct parm *parm; 322 int parent; 323 int ret; 324 325 if (current_rate == rate) 326 return 0; 327 328 debug("%s: setting rate of %ld from %ld to %ld\n", 329 __func__, id, current_rate, rate); 330 331 switch (id) { 332 case CLKID_VPU_0_DIV: 333 parm = &meson_vpu_0_div_parm; 334 parent = meson_vpu_0_div_parent; 335 break; 336 case CLKID_VPU_1_DIV: 337 parm = &meson_vpu_1_div_parm; 338 parent = meson_vpu_1_div_parent; 339 break; 340 case CLKID_VAPB_0_DIV: 341 parm = &meson_vapb_0_div_parm; 342 parent = meson_vapb_0_div_parent; 343 break; 344 case CLKID_VAPB_1_DIV: 345 parm = &meson_vapb_1_div_parm; 346 parent = meson_vapb_1_div_parent; 347 break; 348 default: 349 return -ENOENT; 350 } 351 352 parent_rate = meson_clk_get_rate_by_id(clk, parent); 353 if (IS_ERR_VALUE(parent_rate)) 354 return parent_rate; 355 356 debug("%s: parent rate of %ld is %ld\n", __func__, id, parent_rate); 357 358 /* If can't divide, set parent instead */ 359 if (!parent_rate || rate > parent_rate) 360 return meson_clk_set_rate_by_id(clk, parent, rate, 361 current_rate); 362 363 new_div = DIV_ROUND_CLOSEST(parent_rate, rate); 364 365 debug("%s: new div of %ld is %d\n", __func__, id, new_div); 366 367 /* If overflow, try to set parent rate and retry */ 368 if (!new_div || new_div > (1 << parm->width)) { 369 ret = meson_clk_set_rate_by_id(clk, parent, rate, current_rate); 370 if (IS_ERR_VALUE(ret)) 371 return ret; 372 373 parent_rate = meson_clk_get_rate_by_id(clk, parent); 374 if (IS_ERR_VALUE(parent_rate)) 375 return parent_rate; 376 377 new_div = DIV_ROUND_CLOSEST(parent_rate, rate); 378 379 debug("%s: new new div of %ld is %d\n", __func__, id, new_div); 380 381 if (!new_div || new_div > (1 << parm->width)) 382 return -EINVAL; 383 } 384 385 debug("%s: setting div of %ld to %d\n", __func__, id, new_div); 386 387 regmap_update_bits(priv->map, parm->reg_off, SETPMASK(parm->width, parm->shift), 388 (new_div - 1) << parm->shift); 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 uint 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 regmap_read(priv->map, 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 int i; 498 499 if (IS_ERR_VALUE(cur_parent)) 500 return cur_parent; 501 502 debug("%s: setting parent of %ld from %ld to %ld\n", 503 __func__, id, cur_parent, parent_id); 504 505 if (cur_parent == parent_id) 506 return 0; 507 508 switch (id) { 509 case CLKID_VPU: 510 parm = &meson_vpu_mux_parm; 511 parents = meson_vpu_mux_parents; 512 break; 513 case CLKID_VPU_0_SEL: 514 parm = &meson_vpu_0_mux_parm; 515 parents = meson_vpu_0_1_mux_parents; 516 break; 517 case CLKID_VPU_1_SEL: 518 parm = &meson_vpu_1_mux_parm; 519 parents = meson_vpu_0_1_mux_parents; 520 break; 521 case CLKID_VAPB_SEL: 522 parm = &meson_vapb_sel_mux_parm; 523 parents = meson_vapb_sel_mux_parents; 524 break; 525 case CLKID_VAPB_0_SEL: 526 parm = &meson_vapb_0_mux_parm; 527 parents = meson_vapb_0_1_mux_parents; 528 break; 529 case CLKID_VAPB_1_SEL: 530 parm = &meson_vapb_1_mux_parm; 531 parents = meson_vapb_0_1_mux_parents; 532 break; 533 default: 534 /* Not a mux */ 535 return -ENOENT; 536 } 537 538 for (i = 0 ; i < (1 << parm->width) ; ++i) { 539 if (parents[i] == parent_id) 540 new_index = i; 541 } 542 543 if (IS_ERR_VALUE(new_index)) 544 return new_index; 545 546 debug("%s: new index of %ld is %d\n", __func__, id, new_index); 547 548 regmap_update_bits(priv->map, parm->reg_off, SETPMASK(parm->width, parm->shift), 549 new_index << parm->shift); 550 551 debug("%s: new parent of %ld is %ld\n", 552 __func__, id, meson_mux_get_parent(clk, id)); 553 554 return 0; 555 } 556 557 static ulong meson_mux_get_rate(struct clk *clk, unsigned long id) 558 { 559 int parent = meson_mux_get_parent(clk, id); 560 561 if (IS_ERR_VALUE(parent)) 562 return parent; 563 564 return meson_clk_get_rate_by_id(clk, parent); 565 } 566 567 static unsigned long meson_clk81_get_rate(struct clk *clk) 568 { 569 struct meson_clk *priv = dev_get_priv(clk->dev); 570 unsigned long parent_rate; 571 uint reg; 572 int parents[] = { 573 -1, 574 -1, 575 CLKID_FCLK_DIV7, 576 CLKID_MPLL1, 577 CLKID_MPLL2, 578 CLKID_FCLK_DIV4, 579 CLKID_FCLK_DIV3, 580 CLKID_FCLK_DIV5 581 }; 582 583 /* mux */ 584 regmap_read(priv->map, HHI_MPEG_CLK_CNTL, ®); 585 reg = (reg >> 12) & 7; 586 587 switch (reg) { 588 case 0: 589 parent_rate = XTAL_RATE; 590 break; 591 case 1: 592 return -ENOENT; 593 default: 594 parent_rate = meson_clk_get_rate_by_id(clk, parents[reg]); 595 } 596 597 /* divider */ 598 regmap_read(priv->map, HHI_MPEG_CLK_CNTL, ®); 599 reg = reg & ((1 << 7) - 1); 600 601 /* clk81 divider is zero based */ 602 return parent_rate / (reg + 1); 603 } 604 605 static long mpll_rate_from_params(unsigned long parent_rate, 606 unsigned long sdm, 607 unsigned long n2) 608 { 609 unsigned long divisor = (SDM_DEN * n2) + sdm; 610 611 if (n2 < N2_MIN) 612 return -EINVAL; 613 614 return DIV_ROUND_UP_ULL((u64)parent_rate * SDM_DEN, divisor); 615 } 616 617 static struct parm meson_mpll0_parm[3] = { 618 {HHI_MPLL_CNTL7, 0, 14}, /* psdm */ 619 {HHI_MPLL_CNTL7, 16, 9}, /* pn2 */ 620 }; 621 622 static struct parm meson_mpll1_parm[3] = { 623 {HHI_MPLL_CNTL8, 0, 14}, /* psdm */ 624 {HHI_MPLL_CNTL8, 16, 9}, /* pn2 */ 625 }; 626 627 static struct parm meson_mpll2_parm[3] = { 628 {HHI_MPLL_CNTL9, 0, 14}, /* psdm */ 629 {HHI_MPLL_CNTL9, 16, 9}, /* pn2 */ 630 }; 631 632 /* 633 * MultiPhase Locked Loops are outputs from a PLL with additional frequency 634 * scaling capabilities. MPLL rates are calculated as: 635 * 636 * f(N2_integer, SDM_IN ) = 2.0G/(N2_integer + SDM_IN/16384) 637 */ 638 static ulong meson_mpll_get_rate(struct clk *clk, unsigned long id) 639 { 640 struct meson_clk *priv = dev_get_priv(clk->dev); 641 struct parm *psdm, *pn2; 642 unsigned long sdm, n2; 643 unsigned long parent_rate; 644 uint reg; 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 regmap_read(priv->map, psdm->reg_off, ®); 668 sdm = PARM_GET(psdm->width, psdm->shift, reg); 669 670 regmap_read(priv->map, 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 uint 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 regmap_read(priv->map, pn->reg_off, ®); 712 n = PARM_GET(pn->width, pn->shift, reg); 713 714 regmap_read(priv->map, pm->reg_off, ®); 715 m = PARM_GET(pm->width, pm->shift, reg); 716 717 regmap_read(priv->map, 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 debug("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 debug("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->map = syscon_node_to_regmap(dev_get_parent(dev)->node); 889 if (IS_ERR(priv->map)) 890 return PTR_ERR(priv->map); 891 892 debug("meson-clk: probed\n"); 893 894 return 0; 895 } 896 897 static struct clk_ops meson_clk_ops = { 898 .disable = meson_clk_disable, 899 .enable = meson_clk_enable, 900 .get_rate = meson_clk_get_rate, 901 .set_parent = meson_clk_set_parent, 902 .set_rate = meson_clk_set_rate, 903 }; 904 905 static const struct udevice_id meson_clk_ids[] = { 906 { .compatible = "amlogic,gxbb-clkc" }, 907 { .compatible = "amlogic,gxl-clkc" }, 908 { } 909 }; 910 911 U_BOOT_DRIVER(meson_clk) = { 912 .name = "meson_clk", 913 .id = UCLASS_CLK, 914 .of_match = meson_clk_ids, 915 .priv_auto_alloc_size = sizeof(struct meson_clk), 916 .ops = &meson_clk_ops, 917 .probe = meson_clk_probe, 918 }; 919