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 #define XTAL_RATE 24000000 18 19 struct meson_clk { 20 void __iomem *addr; 21 }; 22 23 static ulong meson_clk_get_rate_by_id(struct clk *clk, unsigned long id); 24 25 struct meson_gate gates[] = { 26 /* Everything Else (EE) domain gates */ 27 MESON_GATE(CLKID_DDR, HHI_GCLK_MPEG0, 0), 28 MESON_GATE(CLKID_DOS, HHI_GCLK_MPEG0, 1), 29 MESON_GATE(CLKID_ISA, HHI_GCLK_MPEG0, 5), 30 MESON_GATE(CLKID_PL301, HHI_GCLK_MPEG0, 6), 31 MESON_GATE(CLKID_PERIPHS, HHI_GCLK_MPEG0, 7), 32 MESON_GATE(CLKID_SPICC, HHI_GCLK_MPEG0, 8), 33 MESON_GATE(CLKID_I2C, HHI_GCLK_MPEG0, 9), 34 MESON_GATE(CLKID_SAR_ADC, HHI_GCLK_MPEG0, 10), 35 MESON_GATE(CLKID_SMART_CARD, HHI_GCLK_MPEG0, 11), 36 MESON_GATE(CLKID_RNG0, HHI_GCLK_MPEG0, 12), 37 MESON_GATE(CLKID_UART0, HHI_GCLK_MPEG0, 13), 38 MESON_GATE(CLKID_SDHC, HHI_GCLK_MPEG0, 14), 39 MESON_GATE(CLKID_STREAM, HHI_GCLK_MPEG0, 15), 40 MESON_GATE(CLKID_ASYNC_FIFO, HHI_GCLK_MPEG0, 16), 41 MESON_GATE(CLKID_SDIO, HHI_GCLK_MPEG0, 17), 42 MESON_GATE(CLKID_ABUF, HHI_GCLK_MPEG0, 18), 43 MESON_GATE(CLKID_HIU_IFACE, HHI_GCLK_MPEG0, 19), 44 MESON_GATE(CLKID_ASSIST_MISC, HHI_GCLK_MPEG0, 23), 45 MESON_GATE(CLKID_SD_EMMC_A, HHI_GCLK_MPEG0, 24), 46 MESON_GATE(CLKID_SD_EMMC_B, HHI_GCLK_MPEG0, 25), 47 MESON_GATE(CLKID_SD_EMMC_C, HHI_GCLK_MPEG0, 26), 48 MESON_GATE(CLKID_SPI, HHI_GCLK_MPEG0, 30), 49 50 MESON_GATE(CLKID_I2S_SPDIF, HHI_GCLK_MPEG1, 2), 51 MESON_GATE(CLKID_ETH, HHI_GCLK_MPEG1, 3), 52 MESON_GATE(CLKID_DEMUX, HHI_GCLK_MPEG1, 4), 53 MESON_GATE(CLKID_AIU_GLUE, HHI_GCLK_MPEG1, 6), 54 MESON_GATE(CLKID_IEC958, HHI_GCLK_MPEG1, 7), 55 MESON_GATE(CLKID_I2S_OUT, HHI_GCLK_MPEG1, 8), 56 MESON_GATE(CLKID_AMCLK, HHI_GCLK_MPEG1, 9), 57 MESON_GATE(CLKID_AIFIFO2, HHI_GCLK_MPEG1, 10), 58 MESON_GATE(CLKID_MIXER, HHI_GCLK_MPEG1, 11), 59 MESON_GATE(CLKID_MIXER_IFACE, HHI_GCLK_MPEG1, 12), 60 MESON_GATE(CLKID_ADC, HHI_GCLK_MPEG1, 13), 61 MESON_GATE(CLKID_BLKMV, HHI_GCLK_MPEG1, 14), 62 MESON_GATE(CLKID_AIU, HHI_GCLK_MPEG1, 15), 63 MESON_GATE(CLKID_UART1, HHI_GCLK_MPEG1, 16), 64 MESON_GATE(CLKID_G2D, HHI_GCLK_MPEG1, 20), 65 MESON_GATE(CLKID_USB0, HHI_GCLK_MPEG1, 21), 66 MESON_GATE(CLKID_USB1, HHI_GCLK_MPEG1, 22), 67 MESON_GATE(CLKID_RESET, HHI_GCLK_MPEG1, 23), 68 MESON_GATE(CLKID_NAND, HHI_GCLK_MPEG1, 24), 69 MESON_GATE(CLKID_DOS_PARSER, HHI_GCLK_MPEG1, 25), 70 MESON_GATE(CLKID_USB, HHI_GCLK_MPEG1, 26), 71 MESON_GATE(CLKID_VDIN1, HHI_GCLK_MPEG1, 28), 72 MESON_GATE(CLKID_AHB_ARB0, HHI_GCLK_MPEG1, 29), 73 MESON_GATE(CLKID_EFUSE, HHI_GCLK_MPEG1, 30), 74 MESON_GATE(CLKID_BOOT_ROM, HHI_GCLK_MPEG1, 31), 75 76 MESON_GATE(CLKID_AHB_DATA_BUS, HHI_GCLK_MPEG2, 1), 77 MESON_GATE(CLKID_AHB_CTRL_BUS, HHI_GCLK_MPEG2, 2), 78 MESON_GATE(CLKID_HDMI_INTR_SYNC, HHI_GCLK_MPEG2, 3), 79 MESON_GATE(CLKID_HDMI_PCLK, HHI_GCLK_MPEG2, 4), 80 MESON_GATE(CLKID_USB1_DDR_BRIDGE, HHI_GCLK_MPEG2, 8), 81 MESON_GATE(CLKID_USB0_DDR_BRIDGE, HHI_GCLK_MPEG2, 9), 82 MESON_GATE(CLKID_MMC_PCLK, HHI_GCLK_MPEG2, 11), 83 MESON_GATE(CLKID_DVIN, HHI_GCLK_MPEG2, 12), 84 MESON_GATE(CLKID_UART2, HHI_GCLK_MPEG2, 15), 85 MESON_GATE(CLKID_SANA, HHI_GCLK_MPEG2, 22), 86 MESON_GATE(CLKID_VPU_INTR, HHI_GCLK_MPEG2, 25), 87 MESON_GATE(CLKID_SEC_AHB_AHB3_BRIDGE, HHI_GCLK_MPEG2, 26), 88 MESON_GATE(CLKID_CLK81_A53, HHI_GCLK_MPEG2, 29), 89 90 MESON_GATE(CLKID_VCLK2_VENCI0, HHI_GCLK_OTHER, 1), 91 MESON_GATE(CLKID_VCLK2_VENCI1, HHI_GCLK_OTHER, 2), 92 MESON_GATE(CLKID_VCLK2_VENCP0, HHI_GCLK_OTHER, 3), 93 MESON_GATE(CLKID_VCLK2_VENCP1, HHI_GCLK_OTHER, 4), 94 MESON_GATE(CLKID_GCLK_VENCI_INT0, HHI_GCLK_OTHER, 8), 95 MESON_GATE(CLKID_DAC_CLK, HHI_GCLK_OTHER, 10), 96 MESON_GATE(CLKID_AOCLK_GATE, HHI_GCLK_OTHER, 14), 97 MESON_GATE(CLKID_IEC958_GATE, HHI_GCLK_OTHER, 16), 98 MESON_GATE(CLKID_ENC480P, HHI_GCLK_OTHER, 20), 99 MESON_GATE(CLKID_RNG1, HHI_GCLK_OTHER, 21), 100 MESON_GATE(CLKID_GCLK_VENCI_INT1, HHI_GCLK_OTHER, 22), 101 MESON_GATE(CLKID_VCLK2_VENCLMCC, HHI_GCLK_OTHER, 24), 102 MESON_GATE(CLKID_VCLK2_VENCL, HHI_GCLK_OTHER, 25), 103 MESON_GATE(CLKID_VCLK_OTHER, HHI_GCLK_OTHER, 26), 104 MESON_GATE(CLKID_EDP, HHI_GCLK_OTHER, 31), 105 106 /* Always On (AO) domain gates */ 107 MESON_GATE(CLKID_AO_MEDIA_CPU, HHI_GCLK_AO, 0), 108 MESON_GATE(CLKID_AO_AHB_SRAM, HHI_GCLK_AO, 1), 109 MESON_GATE(CLKID_AO_AHB_BUS, HHI_GCLK_AO, 2), 110 MESON_GATE(CLKID_AO_IFACE, HHI_GCLK_AO, 3), 111 MESON_GATE(CLKID_AO_I2C, HHI_GCLK_AO, 4), 112 113 /* PLL Gates */ 114 /* CLKID_FCLK_DIV2 is critical for the SCPI Processor */ 115 MESON_GATE(CLKID_FCLK_DIV3, HHI_MPLL_CNTL6, 28), 116 MESON_GATE(CLKID_FCLK_DIV4, HHI_MPLL_CNTL6, 29), 117 MESON_GATE(CLKID_FCLK_DIV5, HHI_MPLL_CNTL6, 30), 118 MESON_GATE(CLKID_FCLK_DIV7, HHI_MPLL_CNTL6, 31), 119 MESON_GATE(CLKID_MPLL0, HHI_MPLL_CNTL7, 14), 120 MESON_GATE(CLKID_MPLL1, HHI_MPLL_CNTL8, 14), 121 MESON_GATE(CLKID_MPLL2, HHI_MPLL_CNTL9, 14), 122 /* CLKID_CLK81 is critical for the system */ 123 124 /* Peripheral Gates */ 125 MESON_GATE(CLKID_SAR_ADC_CLK, HHI_SAR_CLK_CNTL, 8), 126 MESON_GATE(CLKID_SD_EMMC_A_CLK0, HHI_SD_EMMC_CLK_CNTL, 7), 127 MESON_GATE(CLKID_SD_EMMC_B_CLK0, HHI_SD_EMMC_CLK_CNTL, 23), 128 MESON_GATE(CLKID_SD_EMMC_C_CLK0, HHI_NAND_CLK_CNTL, 7), 129 }; 130 131 static int meson_set_gate(struct clk *clk, bool on) 132 { 133 struct meson_clk *priv = dev_get_priv(clk->dev); 134 struct meson_gate *gate; 135 136 if (clk->id >= ARRAY_SIZE(gates)) 137 return -ENOENT; 138 139 gate = &gates[clk->id]; 140 141 if (gate->reg == 0) 142 return 0; 143 144 clrsetbits_le32(priv->addr + gate->reg, 145 BIT(gate->bit), on ? BIT(gate->bit) : 0); 146 return 0; 147 } 148 149 static int meson_clk_enable(struct clk *clk) 150 { 151 return meson_set_gate(clk, true); 152 } 153 154 static int meson_clk_disable(struct clk *clk) 155 { 156 return meson_set_gate(clk, false); 157 } 158 159 static unsigned long meson_clk81_get_rate(struct clk *clk) 160 { 161 struct meson_clk *priv = dev_get_priv(clk->dev); 162 unsigned long parent_rate; 163 u32 reg; 164 int parents[] = { 165 -1, 166 -1, 167 CLKID_FCLK_DIV7, 168 CLKID_MPLL1, 169 CLKID_MPLL2, 170 CLKID_FCLK_DIV4, 171 CLKID_FCLK_DIV3, 172 CLKID_FCLK_DIV5 173 }; 174 175 /* mux */ 176 reg = readl(priv->addr + HHI_MPEG_CLK_CNTL); 177 reg = (reg >> 12) & 7; 178 179 switch (reg) { 180 case 0: 181 parent_rate = XTAL_RATE; 182 break; 183 case 1: 184 return -ENOENT; 185 default: 186 parent_rate = meson_clk_get_rate_by_id(clk, parents[reg]); 187 } 188 189 /* divider */ 190 reg = readl(priv->addr + HHI_MPEG_CLK_CNTL); 191 reg = reg & ((1 << 7) - 1); 192 193 return parent_rate / reg; 194 } 195 196 static long mpll_rate_from_params(unsigned long parent_rate, 197 unsigned long sdm, 198 unsigned long n2) 199 { 200 unsigned long divisor = (SDM_DEN * n2) + sdm; 201 202 if (n2 < N2_MIN) 203 return -EINVAL; 204 205 return DIV_ROUND_UP_ULL((u64)parent_rate * SDM_DEN, divisor); 206 } 207 208 static struct parm meson_mpll0_parm[3] = { 209 {HHI_MPLL_CNTL7, 0, 14}, /* psdm */ 210 {HHI_MPLL_CNTL7, 16, 9}, /* pn2 */ 211 }; 212 213 static struct parm meson_mpll1_parm[3] = { 214 {HHI_MPLL_CNTL8, 0, 14}, /* psdm */ 215 {HHI_MPLL_CNTL8, 16, 9}, /* pn2 */ 216 }; 217 218 static struct parm meson_mpll2_parm[3] = { 219 {HHI_MPLL_CNTL9, 0, 14}, /* psdm */ 220 {HHI_MPLL_CNTL9, 16, 9}, /* pn2 */ 221 }; 222 223 /* 224 * MultiPhase Locked Loops are outputs from a PLL with additional frequency 225 * scaling capabilities. MPLL rates are calculated as: 226 * 227 * f(N2_integer, SDM_IN ) = 2.0G/(N2_integer + SDM_IN/16384) 228 */ 229 static ulong meson_mpll_get_rate(struct clk *clk, unsigned long id) 230 { 231 struct meson_clk *priv = dev_get_priv(clk->dev); 232 struct parm *psdm, *pn2; 233 unsigned long reg, sdm, n2; 234 unsigned long parent_rate; 235 236 switch (id) { 237 case CLKID_MPLL0: 238 psdm = &meson_mpll0_parm[0]; 239 pn2 = &meson_mpll0_parm[1]; 240 break; 241 case CLKID_MPLL1: 242 psdm = &meson_mpll1_parm[0]; 243 pn2 = &meson_mpll1_parm[1]; 244 break; 245 case CLKID_MPLL2: 246 psdm = &meson_mpll2_parm[0]; 247 pn2 = &meson_mpll2_parm[1]; 248 break; 249 default: 250 return -ENOENT; 251 } 252 253 parent_rate = meson_clk_get_rate_by_id(clk, CLKID_FIXED_PLL); 254 if (IS_ERR_VALUE(parent_rate)) 255 return parent_rate; 256 257 reg = readl(priv->addr + psdm->reg_off); 258 sdm = PARM_GET(psdm->width, psdm->shift, reg); 259 260 reg = readl(priv->addr + pn2->reg_off); 261 n2 = PARM_GET(pn2->width, pn2->shift, reg); 262 263 return mpll_rate_from_params(parent_rate, sdm, n2); 264 } 265 266 static struct parm meson_fixed_pll_parm[3] = { 267 {HHI_MPLL_CNTL, 0, 9}, /* pm */ 268 {HHI_MPLL_CNTL, 9, 5}, /* pn */ 269 {HHI_MPLL_CNTL, 16, 2}, /* pod */ 270 }; 271 272 static struct parm meson_sys_pll_parm[3] = { 273 {HHI_SYS_PLL_CNTL, 0, 9}, /* pm */ 274 {HHI_SYS_PLL_CNTL, 9, 5}, /* pn */ 275 {HHI_SYS_PLL_CNTL, 10, 2}, /* pod */ 276 }; 277 278 static ulong meson_pll_get_rate(struct clk *clk, unsigned long id) 279 { 280 struct meson_clk *priv = dev_get_priv(clk->dev); 281 struct parm *pm, *pn, *pod; 282 unsigned long parent_rate_mhz = XTAL_RATE / 1000000; 283 u16 n, m, od; 284 u32 reg; 285 286 switch (id) { 287 case CLKID_FIXED_PLL: 288 pm = &meson_fixed_pll_parm[0]; 289 pn = &meson_fixed_pll_parm[1]; 290 pod = &meson_fixed_pll_parm[2]; 291 break; 292 case CLKID_SYS_PLL: 293 pm = &meson_sys_pll_parm[0]; 294 pn = &meson_sys_pll_parm[1]; 295 pod = &meson_sys_pll_parm[2]; 296 break; 297 default: 298 return -ENOENT; 299 } 300 301 reg = readl(priv->addr + pn->reg_off); 302 n = PARM_GET(pn->width, pn->shift, reg); 303 304 reg = readl(priv->addr + pm->reg_off); 305 m = PARM_GET(pm->width, pm->shift, reg); 306 307 reg = readl(priv->addr + pod->reg_off); 308 od = PARM_GET(pod->width, pod->shift, reg); 309 310 return ((parent_rate_mhz * m / n) >> od) * 1000000; 311 } 312 313 static ulong meson_clk_get_rate_by_id(struct clk *clk, unsigned long id) 314 { 315 ulong rate; 316 317 switch (id) { 318 case CLKID_FIXED_PLL: 319 case CLKID_SYS_PLL: 320 rate = meson_pll_get_rate(clk, id); 321 break; 322 case CLKID_FCLK_DIV2: 323 rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 2; 324 break; 325 case CLKID_FCLK_DIV3: 326 rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 3; 327 break; 328 case CLKID_FCLK_DIV4: 329 rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 4; 330 break; 331 case CLKID_FCLK_DIV5: 332 rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 5; 333 break; 334 case CLKID_FCLK_DIV7: 335 rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 7; 336 break; 337 case CLKID_MPLL0: 338 case CLKID_MPLL1: 339 case CLKID_MPLL2: 340 rate = meson_mpll_get_rate(clk, id); 341 break; 342 case CLKID_CLK81: 343 rate = meson_clk81_get_rate(clk); 344 break; 345 default: 346 if (gates[id].reg != 0) { 347 /* a clock gate */ 348 rate = meson_clk81_get_rate(clk); 349 break; 350 } 351 return -ENOENT; 352 } 353 354 printf("clock %lu has rate %lu\n", id, rate); 355 return rate; 356 } 357 358 static ulong meson_clk_get_rate(struct clk *clk) 359 { 360 return meson_clk_get_rate_by_id(clk, clk->id); 361 } 362 363 static int meson_clk_probe(struct udevice *dev) 364 { 365 struct meson_clk *priv = dev_get_priv(dev); 366 367 priv->addr = dev_read_addr_ptr(dev); 368 369 debug("meson-clk: probed at addr %p\n", priv->addr); 370 371 return 0; 372 } 373 374 static struct clk_ops meson_clk_ops = { 375 .disable = meson_clk_disable, 376 .enable = meson_clk_enable, 377 .get_rate = meson_clk_get_rate, 378 }; 379 380 static const struct udevice_id meson_clk_ids[] = { 381 { .compatible = "amlogic,gxbb-clkc" }, 382 { .compatible = "amlogic,gxl-clkc" }, 383 { } 384 }; 385 386 U_BOOT_DRIVER(meson_clk) = { 387 .name = "meson_clk", 388 .id = UCLASS_CLK, 389 .of_match = meson_clk_ids, 390 .priv_auto_alloc_size = sizeof(struct meson_clk), 391 .ops = &meson_clk_ops, 392 .probe = meson_clk_probe, 393 }; 394