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 <log.h> 10#include <asm/arch/clock-g12a.h> 11#include <asm/io.h> 12#include <clk-uclass.h> 13#include <dm.h> 14#include <regmap.h> 15#include <syscon.h> 16#include <div64.h> 17#include <dt-bindings/clock/g12a-clkc.h> 18#include <linux/bitops.h> 19#include <linux/delay.h> 20#include <linux/err.h> 21#include <linux/kernel.h> 22#include "clk_meson.h" 23 24/* This driver support only basic clock tree operations : 25 * - Can calculate clock frequency on a limited tree 26 * - Can Read muxes and basic dividers (0-based only) 27 * - Can enable/disable gates with limited propagation 28 * - Can reparent without propagation, only on muxes 29 * - Can set rates without reparenting 30 * This driver is adapted to what is actually supported by U-Boot 31 */ 32 33/* Only the clocks ids we don't want to expose, such as the internal muxes 34 * and dividers of composite clocks, will remain defined here. 35 */ 36#define CLKID_MPEG_SEL 8 37#define CLKID_MPEG_DIV 9 38#define CLKID_SD_EMMC_A_CLK0_SEL 63 39#define CLKID_SD_EMMC_A_CLK0_DIV 64 40#define CLKID_SD_EMMC_B_CLK0_SEL 65 41#define CLKID_SD_EMMC_B_CLK0_DIV 66 42#define CLKID_SD_EMMC_C_CLK0_SEL 67 43#define CLKID_SD_EMMC_C_CLK0_DIV 68 44#define CLKID_MPLL0_DIV 69 45#define CLKID_MPLL1_DIV 70 46#define CLKID_MPLL2_DIV 71 47#define CLKID_MPLL3_DIV 72 48#define CLKID_MPLL_PREDIV 73 49#define CLKID_FCLK_DIV2_DIV 75 50#define CLKID_FCLK_DIV3_DIV 76 51#define CLKID_FCLK_DIV4_DIV 77 52#define CLKID_FCLK_DIV5_DIV 78 53#define CLKID_FCLK_DIV7_DIV 79 54#define CLKID_FCLK_DIV2P5_DIV 100 55#define CLKID_FIXED_PLL_DCO 101 56#define CLKID_SYS_PLL_DCO 102 57#define CLKID_GP0_PLL_DCO 103 58#define CLKID_HIFI_PLL_DCO 104 59#define CLKID_VPU_0_DIV 111 60#define CLKID_VPU_1_DIV 114 61#define CLKID_VAPB_0_DIV 118 62#define CLKID_VAPB_1_DIV 121 63#define CLKID_HDMI_PLL_DCO 125 64#define CLKID_HDMI_PLL_OD 126 65#define CLKID_HDMI_PLL_OD2 127 66#define CLKID_VID_PLL_SEL 130 67#define CLKID_VID_PLL_DIV 131 68#define CLKID_VCLK_SEL 132 69#define CLKID_VCLK2_SEL 133 70#define CLKID_VCLK_INPUT 134 71#define CLKID_VCLK2_INPUT 135 72#define CLKID_VCLK_DIV 136 73#define CLKID_VCLK2_DIV 137 74#define CLKID_VCLK_DIV2_EN 140 75#define CLKID_VCLK_DIV4_EN 141 76#define CLKID_VCLK_DIV6_EN 142 77#define CLKID_VCLK_DIV12_EN 143 78#define CLKID_VCLK2_DIV2_EN 144 79#define CLKID_VCLK2_DIV4_EN 145 80#define CLKID_VCLK2_DIV6_EN 146 81#define CLKID_VCLK2_DIV12_EN 147 82#define CLKID_CTS_ENCI_SEL 158 83#define CLKID_CTS_ENCP_SEL 159 84#define CLKID_CTS_VDAC_SEL 160 85#define CLKID_HDMI_TX_SEL 161 86#define CLKID_HDMI_SEL 166 87#define CLKID_HDMI_DIV 167 88#define CLKID_MALI_0_DIV 170 89#define CLKID_MALI_1_DIV 173 90 91#define CLKID_XTAL 0x10000000 92 93#define XTAL_RATE 24000000 94 95struct meson_clk { 96 struct regmap *map; 97}; 98 99static ulong meson_div_get_rate(struct clk *clk, unsigned long id); 100static ulong meson_div_set_rate(struct clk *clk, unsigned long id, ulong rate, 101 ulong current_rate); 102static ulong meson_mux_set_parent(struct clk *clk, unsigned long id, 103 unsigned long parent_id); 104static ulong meson_mux_get_rate(struct clk *clk, unsigned long id); 105static ulong meson_clk_set_rate_by_id(struct clk *clk, unsigned long id, 106 ulong rate, ulong current_rate); 107static ulong meson_mux_get_parent(struct clk *clk, unsigned long id); 108static ulong meson_clk_get_rate_by_id(struct clk *clk, unsigned long id); 109 110#define NUM_CLKS 178 111 112static struct meson_gate gates[NUM_CLKS] = { 113 /* Everything Else (EE) domain gates */ 114 MESON_GATE(CLKID_SPICC0, HHI_GCLK_MPEG0, 8), 115 MESON_GATE(CLKID_I2C, HHI_GCLK_MPEG0, 9), 116 MESON_GATE(CLKID_UART0, HHI_GCLK_MPEG0, 13), 117 MESON_GATE(CLKID_SPICC1, HHI_GCLK_MPEG0, 14), 118 MESON_GATE(CLKID_SD_EMMC_A, HHI_GCLK_MPEG0, 4), 119 MESON_GATE(CLKID_SD_EMMC_B, HHI_GCLK_MPEG0, 25), 120 MESON_GATE(CLKID_SD_EMMC_C, HHI_GCLK_MPEG0, 26), 121 MESON_GATE(CLKID_ETH, HHI_GCLK_MPEG1, 3), 122 MESON_GATE(CLKID_UART1, HHI_GCLK_MPEG1, 16), 123 MESON_GATE(CLKID_PCIE_COMB, HHI_GCLK_MPEG1, 24), 124 MESON_GATE(CLKID_USB, HHI_GCLK_MPEG1, 25), 125 MESON_GATE(CLKID_PCIE_PHY, HHI_GCLK_MPEG1, 27), 126 MESON_GATE(CLKID_HTX_PCLK, HHI_GCLK_MPEG2, 4), 127 MESON_GATE(CLKID_USB1_DDR_BRIDGE, HHI_GCLK_MPEG2, 8), 128 MESON_GATE(CLKID_VPU_INTR, HHI_GCLK_MPEG2, 25), 129 130 /* Peripheral Gates */ 131 MESON_GATE(CLKID_FCLK_DIV2, HHI_FIX_PLL_CNTL1, 24), 132 MESON_GATE(CLKID_FCLK_DIV3, HHI_FIX_PLL_CNTL1, 20), 133 MESON_GATE(CLKID_FCLK_DIV4, HHI_FIX_PLL_CNTL1, 21), 134 MESON_GATE(CLKID_FCLK_DIV5, HHI_FIX_PLL_CNTL1, 22), 135 MESON_GATE(CLKID_FCLK_DIV7, HHI_FIX_PLL_CNTL1, 23), 136 MESON_GATE(CLKID_SD_EMMC_A_CLK0, HHI_SD_EMMC_CLK_CNTL, 7), 137 MESON_GATE(CLKID_SD_EMMC_B_CLK0, HHI_SD_EMMC_CLK_CNTL, 23), 138 MESON_GATE(CLKID_SD_EMMC_C_CLK0, HHI_NAND_CLK_CNTL, 7), 139 MESON_GATE(CLKID_VPU_0, HHI_VPU_CLK_CNTL, 8), 140 MESON_GATE(CLKID_VPU_1, HHI_VPU_CLK_CNTL, 24), 141 MESON_GATE(CLKID_VAPB_0, HHI_VAPBCLK_CNTL, 8), 142 MESON_GATE(CLKID_VAPB_1, HHI_VAPBCLK_CNTL, 24), 143 MESON_GATE(CLKID_VAPB, HHI_VAPBCLK_CNTL, 30), 144 MESON_GATE(CLKID_HDMI, HHI_HDMI_CLK_CNTL, 8), 145}; 146 147static int meson_set_gate_by_id(struct clk *clk, unsigned long id, bool on) 148{ 149 struct meson_clk *priv = dev_get_priv(clk->dev); 150 struct meson_gate *gate; 151 152 debug("%s: %sabling %ld\n", __func__, on ? "en" : "dis", id); 153 154 /* Propagate through muxes */ 155 switch (id) { 156 case CLKID_VPU: 157 return meson_set_gate_by_id(clk, 158 meson_mux_get_parent(clk, CLKID_VPU), on); 159 case CLKID_VAPB_SEL: 160 return meson_set_gate_by_id(clk, 161 meson_mux_get_parent(clk, CLKID_VAPB_SEL), on); 162 } 163 164 if (id >= ARRAY_SIZE(gates)) 165 return -ENOENT; 166 167 gate = &gates[id]; 168 169 if (gate->reg == 0) 170 return 0; 171 172 debug("%s: really %sabling %ld\n", __func__, on ? "en" : "dis", id); 173 174 regmap_update_bits(priv->map, gate->reg, 175 BIT(gate->bit), on ? BIT(gate->bit) : 0); 176 177 /* Propagate to next gate(s) */ 178 switch (id) { 179 case CLKID_VAPB: 180 return meson_set_gate_by_id(clk, CLKID_VAPB_SEL, on); 181 case CLKID_VAPB_0: 182 return meson_set_gate_by_id(clk, 183 meson_mux_get_parent(clk, CLKID_VAPB_0_SEL), on); 184 case CLKID_VAPB_1: 185 return meson_set_gate_by_id(clk, 186 meson_mux_get_parent(clk, CLKID_VAPB_0_SEL), on); 187 case CLKID_VPU_0: 188 return meson_set_gate_by_id(clk, 189 meson_mux_get_parent(clk, CLKID_VPU_0_SEL), on); 190 case CLKID_VPU_1: 191 return meson_set_gate_by_id(clk, 192 meson_mux_get_parent(clk, CLKID_VPU_1_SEL), on); 193 } 194 195 return 0; 196} 197 198static int meson_clk_enable(struct clk *clk) 199{ 200 return meson_set_gate_by_id(clk, clk->id, true); 201} 202 203static int meson_clk_disable(struct clk *clk) 204{ 205 return meson_set_gate_by_id(clk, clk->id, false); 206} 207 208static struct parm meson_vpu_0_div_parm = { 209 HHI_VPU_CLK_CNTL, 0, 7, 210}; 211 212int meson_vpu_0_div_parent = CLKID_VPU_0_SEL; 213 214static struct parm meson_vpu_1_div_parm = { 215 HHI_VPU_CLK_CNTL, 16, 7, 216}; 217 218int meson_vpu_1_div_parent = CLKID_VPU_1_SEL; 219 220static struct parm meson_vapb_0_div_parm = { 221 HHI_VAPBCLK_CNTL, 0, 7, 222}; 223 224int meson_vapb_0_div_parent = CLKID_VAPB_0_SEL; 225 226static struct parm meson_vapb_1_div_parm = { 227 HHI_VAPBCLK_CNTL, 16, 7, 228}; 229 230int meson_vapb_1_div_parent = CLKID_VAPB_1_SEL; 231 232static struct parm meson_hdmi_div_parm = { 233 HHI_HDMI_CLK_CNTL, 0, 7, 234}; 235 236int meson_hdmi_div_parent = CLKID_HDMI_SEL; 237 238static ulong meson_div_get_rate(struct clk *clk, unsigned long id) 239{ 240 struct meson_clk *priv = dev_get_priv(clk->dev); 241 unsigned int rate, parent_rate; 242 struct parm *parm; 243 int parent; 244 uint reg; 245 246 switch (id) { 247 case CLKID_VPU_0_DIV: 248 parm = &meson_vpu_0_div_parm; 249 parent = meson_vpu_0_div_parent; 250 break; 251 case CLKID_VPU_1_DIV: 252 parm = &meson_vpu_1_div_parm; 253 parent = meson_vpu_1_div_parent; 254 break; 255 case CLKID_VAPB_0_DIV: 256 parm = &meson_vapb_0_div_parm; 257 parent = meson_vapb_0_div_parent; 258 break; 259 case CLKID_VAPB_1_DIV: 260 parm = &meson_vapb_1_div_parm; 261 parent = meson_vapb_1_div_parent; 262 break; 263 case CLKID_HDMI_DIV: 264 parm = &meson_hdmi_div_parm; 265 parent = meson_hdmi_div_parent; 266 break; 267 default: 268 return -ENOENT; 269 } 270 271 regmap_read(priv->map, parm->reg_off, ®); 272 reg = PARM_GET(parm->width, parm->shift, reg); 273 274 debug("%s: div of %ld is %d\n", __func__, id, reg + 1); 275 276 parent_rate = meson_clk_get_rate_by_id(clk, parent); 277 if (IS_ERR_VALUE(parent_rate)) 278 return parent_rate; 279 280 debug("%s: parent rate of %ld is %d\n", __func__, id, parent_rate); 281 282 rate = parent_rate / (reg + 1); 283 284 debug("%s: rate of %ld is %d\n", __func__, id, rate); 285 286 return rate; 287} 288 289static ulong meson_div_set_rate(struct clk *clk, unsigned long id, ulong rate, 290 ulong current_rate) 291{ 292 struct meson_clk *priv = dev_get_priv(clk->dev); 293 unsigned int new_div = -EINVAL; 294 unsigned long parent_rate; 295 struct parm *parm; 296 int parent; 297 int ret; 298 299 if (current_rate == rate) 300 return 0; 301 302 debug("%s: setting rate of %ld from %ld to %ld\n", 303 __func__, id, current_rate, rate); 304 305 switch (id) { 306 case CLKID_VPU_0_DIV: 307 parm = &meson_vpu_0_div_parm; 308 parent = meson_vpu_0_div_parent; 309 break; 310 case CLKID_VPU_1_DIV: 311 parm = &meson_vpu_1_div_parm; 312 parent = meson_vpu_1_div_parent; 313 break; 314 case CLKID_VAPB_0_DIV: 315 parm = &meson_vapb_0_div_parm; 316 parent = meson_vapb_0_div_parent; 317 break; 318 case CLKID_VAPB_1_DIV: 319 parm = &meson_vapb_1_div_parm; 320 parent = meson_vapb_1_div_parent; 321 break; 322 case CLKID_HDMI_DIV: 323 parm = &meson_hdmi_div_parm; 324 parent = meson_hdmi_div_parent; 325 break; 326 default: 327 return -ENOENT; 328 } 329 330 parent_rate = meson_clk_get_rate_by_id(clk, parent); 331 if (IS_ERR_VALUE(parent_rate)) 332 return parent_rate; 333 334 debug("%s: parent rate of %ld is %ld\n", __func__, id, parent_rate); 335 336 /* If can't divide, set parent instead */ 337 if (!parent_rate || rate > parent_rate) 338 return meson_clk_set_rate_by_id(clk, parent, rate, 339 current_rate); 340 341 new_div = DIV_ROUND_CLOSEST(parent_rate, rate); 342 343 debug("%s: new div of %ld is %d\n", __func__, id, new_div); 344 345 /* If overflow, try to set parent rate and retry */ 346 if (!new_div || new_div > (1 << parm->width)) { 347 ret = meson_clk_set_rate_by_id(clk, parent, rate, current_rate); 348 if (IS_ERR_VALUE(ret)) 349 return ret; 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 new_div = DIV_ROUND_CLOSEST(parent_rate, rate); 356 357 debug("%s: new new div of %ld is %d\n", __func__, id, new_div); 358 359 if (!new_div || new_div > (1 << parm->width)) 360 return -EINVAL; 361 } 362 363 debug("%s: setting div of %ld to %d\n", __func__, id, new_div); 364 365 regmap_update_bits(priv->map, parm->reg_off, 366 SETPMASK(parm->width, parm->shift), 367 (new_div - 1) << parm->shift); 368 369 debug("%s: new rate of %ld is %ld\n", 370 __func__, id, meson_div_get_rate(clk, id)); 371 372 return 0; 373} 374 375static struct parm meson_vpu_mux_parm = { 376 HHI_VPU_CLK_CNTL, 31, 1, 377}; 378 379int meson_vpu_mux_parents[] = { 380 CLKID_VPU_0, 381 CLKID_VPU_1, 382}; 383 384static struct parm meson_vpu_0_mux_parm = { 385 HHI_VPU_CLK_CNTL, 9, 3, 386}; 387 388static struct parm meson_vpu_1_mux_parm = { 389 HHI_VPU_CLK_CNTL, 25, 3, 390}; 391 392static int meson_vpu_0_1_mux_parents[] = { 393 CLKID_FCLK_DIV3, 394 CLKID_FCLK_DIV4, 395 CLKID_FCLK_DIV5, 396 CLKID_FCLK_DIV7, 397 -ENOENT, 398 -ENOENT, 399 -ENOENT, 400 -ENOENT, 401}; 402 403static struct parm meson_vapb_sel_mux_parm = { 404 HHI_VAPBCLK_CNTL, 31, 1, 405}; 406 407int meson_vapb_sel_mux_parents[] = { 408 CLKID_VAPB_0, 409 CLKID_VAPB_1, 410}; 411 412static struct parm meson_vapb_0_mux_parm = { 413 HHI_VAPBCLK_CNTL, 9, 2, 414}; 415 416static struct parm meson_vapb_1_mux_parm = { 417 HHI_VAPBCLK_CNTL, 25, 2, 418}; 419 420static int meson_vapb_0_1_mux_parents[] = { 421 CLKID_FCLK_DIV4, 422 CLKID_FCLK_DIV3, 423 CLKID_FCLK_DIV5, 424 CLKID_FCLK_DIV7, 425}; 426 427static struct parm meson_hdmi_mux_parm = { 428 HHI_HDMI_CLK_CNTL, 9, 2, 429}; 430 431static int meson_hdmi_mux_parents[] = { 432 CLKID_XTAL, 433 CLKID_FCLK_DIV4, 434 CLKID_FCLK_DIV3, 435 CLKID_FCLK_DIV5, 436}; 437 438static ulong meson_mux_get_parent(struct clk *clk, unsigned long id) 439{ 440 struct meson_clk *priv = dev_get_priv(clk->dev); 441 struct parm *parm; 442 int *parents; 443 uint reg; 444 445 switch (id) { 446 case CLKID_VPU: 447 parm = &meson_vpu_mux_parm; 448 parents = meson_vpu_mux_parents; 449 break; 450 case CLKID_VPU_0_SEL: 451 parm = &meson_vpu_0_mux_parm; 452 parents = meson_vpu_0_1_mux_parents; 453 break; 454 case CLKID_VPU_1_SEL: 455 parm = &meson_vpu_1_mux_parm; 456 parents = meson_vpu_0_1_mux_parents; 457 break; 458 case CLKID_VAPB_SEL: 459 parm = &meson_vapb_sel_mux_parm; 460 parents = meson_vapb_sel_mux_parents; 461 break; 462 case CLKID_VAPB_0_SEL: 463 parm = &meson_vapb_0_mux_parm; 464 parents = meson_vapb_0_1_mux_parents; 465 break; 466 case CLKID_VAPB_1_SEL: 467 parm = &meson_vapb_1_mux_parm; 468 parents = meson_vapb_0_1_mux_parents; 469 break; 470 case CLKID_HDMI_SEL: 471 parm = &meson_hdmi_mux_parm; 472 parents = meson_hdmi_mux_parents; 473 break; 474 default: 475 return -ENOENT; 476 } 477 478 regmap_read(priv->map, parm->reg_off, ®); 479 reg = PARM_GET(parm->width, parm->shift, reg); 480 481 debug("%s: parent of %ld is %d (%d)\n", 482 __func__, id, parents[reg], reg); 483 484 return parents[reg]; 485} 486 487static ulong meson_mux_set_parent(struct clk *clk, unsigned long id, 488 unsigned long parent_id) 489{ 490 unsigned long cur_parent = meson_mux_get_parent(clk, id); 491 struct meson_clk *priv = dev_get_priv(clk->dev); 492 unsigned int new_index = -EINVAL; 493 struct parm *parm; 494 int *parents; 495 int i; 496 497 if (IS_ERR_VALUE(cur_parent)) 498 return cur_parent; 499 500 debug("%s: setting parent of %ld from %ld to %ld\n", 501 __func__, id, cur_parent, parent_id); 502 503 if (cur_parent == parent_id) 504 return 0; 505 506 switch (id) { 507 case CLKID_VPU: 508 parm = &meson_vpu_mux_parm; 509 parents = meson_vpu_mux_parents; 510 break; 511 case CLKID_VPU_0_SEL: 512 parm = &meson_vpu_0_mux_parm; 513 parents = meson_vpu_0_1_mux_parents; 514 break; 515 case CLKID_VPU_1_SEL: 516 parm = &meson_vpu_1_mux_parm; 517 parents = meson_vpu_0_1_mux_parents; 518 break; 519 case CLKID_VAPB_SEL: 520 parm = &meson_vapb_sel_mux_parm; 521 parents = meson_vapb_sel_mux_parents; 522 break; 523 case CLKID_VAPB_0_SEL: 524 parm = &meson_vapb_0_mux_parm; 525 parents = meson_vapb_0_1_mux_parents; 526 break; 527 case CLKID_VAPB_1_SEL: 528 parm = &meson_vapb_1_mux_parm; 529 parents = meson_vapb_0_1_mux_parents; 530 break; 531 case CLKID_HDMI_SEL: 532 parm = &meson_hdmi_mux_parm; 533 parents = meson_hdmi_mux_parents; 534 break; 535 default: 536 /* Not a mux */ 537 return -ENOENT; 538 } 539 540 for (i = 0 ; i < (1 << parm->width) ; ++i) { 541 if (parents[i] == parent_id) 542 new_index = i; 543 } 544 545 if (IS_ERR_VALUE(new_index)) 546 return new_index; 547 548 debug("%s: new index of %ld is %d\n", __func__, id, new_index); 549 550 regmap_update_bits(priv->map, parm->reg_off, 551 SETPMASK(parm->width, parm->shift), 552 new_index << parm->shift); 553 554 debug("%s: new parent of %ld is %ld\n", 555 __func__, id, meson_mux_get_parent(clk, id)); 556 557 return 0; 558} 559 560static ulong meson_mux_get_rate(struct clk *clk, unsigned long id) 561{ 562 int parent = meson_mux_get_parent(clk, id); 563 564 if (IS_ERR_VALUE(parent)) 565 return parent; 566 567 return meson_clk_get_rate_by_id(clk, parent); 568} 569 570static unsigned long meson_clk81_get_rate(struct clk *clk) 571{ 572 struct meson_clk *priv = dev_get_priv(clk->dev); 573 unsigned long parent_rate; 574 uint reg; 575 int parents[] = { 576 CLKID_XTAL, 577 -1, 578 CLKID_FCLK_DIV7, 579 CLKID_MPLL1, 580 CLKID_MPLL2, 581 CLKID_FCLK_DIV4, 582 CLKID_FCLK_DIV3, 583 CLKID_FCLK_DIV5 584 }; 585 586 /* mux */ 587 regmap_read(priv->map, HHI_MPEG_CLK_CNTL, ®); 588 reg = (reg >> 12) & 7; 589 590 switch (reg) { 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 return parent_rate / reg; 602} 603 604static long mpll_rate_from_params(unsigned long parent_rate, 605 unsigned long sdm, 606 unsigned long n2) 607{ 608 unsigned long divisor = (SDM_DEN * n2) + sdm; 609 610 if (n2 < N2_MIN) 611 return -EINVAL; 612 613 return DIV_ROUND_UP_ULL((u64)parent_rate * SDM_DEN, divisor); 614} 615 616static struct parm meson_mpll0_parm[2] = { 617 {HHI_MPLL_CNTL1, 0, 14}, /* psdm */ 618 {HHI_MPLL_CNTL1, 20, 9}, /* pn2 */ 619}; 620 621static struct parm meson_mpll1_parm[2] = { 622 {HHI_MPLL_CNTL3, 0, 14}, /* psdm */ 623 {HHI_MPLL_CNTL3, 20, 9}, /* pn2 */ 624}; 625 626static struct parm meson_mpll2_parm[2] = { 627 {HHI_MPLL_CNTL5, 0, 14}, /* psdm */ 628 {HHI_MPLL_CNTL5, 20, 9}, /* pn2 */ 629}; 630 631/* 632 * MultiPhase Locked Loops are outputs from a PLL with additional frequency 633 * scaling capabilities. MPLL rates are calculated as: 634 * 635 * f(N2_integer, SDM_IN ) = 2.0G/(N2_integer + SDM_IN/16384) 636 */ 637static ulong meson_mpll_get_rate(struct clk *clk, unsigned long id) 638{ 639 struct meson_clk *priv = dev_get_priv(clk->dev); 640 struct parm *psdm, *pn2; 641 unsigned long sdm, n2; 642 unsigned long parent_rate; 643 uint reg; 644 645 switch (id) { 646 case CLKID_MPLL0: 647 psdm = &meson_mpll0_parm[0]; 648 pn2 = &meson_mpll0_parm[1]; 649 break; 650 case CLKID_MPLL1: 651 psdm = &meson_mpll1_parm[0]; 652 pn2 = &meson_mpll1_parm[1]; 653 break; 654 case CLKID_MPLL2: 655 psdm = &meson_mpll2_parm[0]; 656 pn2 = &meson_mpll2_parm[1]; 657 break; 658 default: 659 return -ENOENT; 660 } 661 662 parent_rate = meson_clk_get_rate_by_id(clk, CLKID_FIXED_PLL); 663 if (IS_ERR_VALUE(parent_rate)) 664 return parent_rate; 665 666 regmap_read(priv->map, psdm->reg_off, ®); 667 sdm = PARM_GET(psdm->width, psdm->shift, reg); 668 669 regmap_read(priv->map, pn2->reg_off, ®); 670 n2 = PARM_GET(pn2->width, pn2->shift, reg); 671 672 return mpll_rate_from_params(parent_rate, sdm, n2); 673} 674 675static struct parm meson_fixed_pll_parm[4] = { 676 {HHI_FIX_PLL_CNTL0, 0, 9}, /* pm */ 677 {HHI_FIX_PLL_CNTL0, 10, 5}, /* pn */ 678 {HHI_FIX_PLL_CNTL0, 16, 2}, /* pod */ 679 {HHI_FIX_PLL_CNTL1, 0, 17}, /* pfrac */ 680}; 681 682static struct parm meson_sys_pll_parm[3] = { 683 {HHI_SYS_PLL_CNTL0, 0, 9}, /* pm */ 684 {HHI_SYS_PLL_CNTL0, 10, 5}, /* pn */ 685 {HHI_SYS_PLL_CNTL0, 16, 3}, /* pod */ 686}; 687 688static 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, *pfrac = NULL; 692 unsigned long parent_rate_mhz = XTAL_RATE / 1000000; 693 u16 n, m, od, frac; 694 ulong rate; 695 uint reg; 696 697 /* 698 * FIXME: Between the unit conversion and the missing frac, we know 699 * rate will be slightly off ... 700 */ 701 702 switch (id) { 703 case CLKID_FIXED_PLL: 704 pm = &meson_fixed_pll_parm[0]; 705 pn = &meson_fixed_pll_parm[1]; 706 pod = &meson_fixed_pll_parm[2]; 707 pfrac = &meson_fixed_pll_parm[3]; 708 break; 709 case CLKID_SYS_PLL: 710 pm = &meson_sys_pll_parm[0]; 711 pn = &meson_sys_pll_parm[1]; 712 pod = &meson_sys_pll_parm[2]; 713 break; 714 default: 715 return -ENOENT; 716 } 717 718 regmap_read(priv->map, pn->reg_off, ®); 719 n = PARM_GET(pn->width, pn->shift, reg); 720 721 regmap_read(priv->map, pm->reg_off, ®); 722 m = PARM_GET(pm->width, pm->shift, reg); 723 724 regmap_read(priv->map, pod->reg_off, ®); 725 od = PARM_GET(pod->width, pod->shift, reg); 726 727 rate = parent_rate_mhz * m; 728 729 if (pfrac) { 730 ulong frac_rate; 731 732 regmap_read(priv->map, pfrac->reg_off, ®); 733 frac = PARM_GET(pfrac->width - 1, pfrac->shift, reg); 734 735 frac_rate = DIV_ROUND_UP_ULL((u64)parent_rate_mhz * frac, 736 1 << (pfrac->width - 2)); 737 738 if (frac & BIT(pfrac->width - 1)) 739 rate -= frac_rate; 740 else 741 rate += frac_rate; 742 } 743 744 return (DIV_ROUND_UP_ULL(rate, n) >> od) * 1000000; 745} 746 747static struct parm meson_pcie_pll_parm[3] = { 748 {HHI_PCIE_PLL_CNTL0, 0, 8}, /* pm */ 749 {HHI_PCIE_PLL_CNTL0, 10, 5}, /* pn */ 750 {HHI_PCIE_PLL_CNTL0, 16, 5}, /* pod */ 751}; 752 753static ulong meson_pcie_pll_get_rate(struct clk *clk) 754{ 755 struct meson_clk *priv = dev_get_priv(clk->dev); 756 struct parm *pm, *pn, *pod; 757 unsigned long parent_rate_mhz = XTAL_RATE / 1000000; 758 u16 n, m, od; 759 uint reg; 760 761 pm = &meson_pcie_pll_parm[0]; 762 pn = &meson_pcie_pll_parm[1]; 763 pod = &meson_pcie_pll_parm[2]; 764 765 regmap_read(priv->map, pn->reg_off, ®); 766 n = PARM_GET(pn->width, pn->shift, reg); 767 768 regmap_read(priv->map, pm->reg_off, ®); 769 m = PARM_GET(pm->width, pm->shift, reg); 770 771 regmap_read(priv->map, pod->reg_off, ®); 772 od = PARM_GET(pod->width, pod->shift, reg); 773 774 return ((parent_rate_mhz * m / n) / 2 / od / 2) * 1000000; 775} 776 777static ulong meson_clk_get_rate_by_id(struct clk *clk, unsigned long id) 778{ 779 ulong rate; 780 781 switch (id) { 782 case CLKID_XTAL: 783 rate = XTAL_RATE; 784 break; 785 case CLKID_FIXED_PLL: 786 case CLKID_SYS_PLL: 787 rate = meson_pll_get_rate(clk, id); 788 break; 789 case CLKID_FCLK_DIV2: 790 rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 2; 791 break; 792 case CLKID_FCLK_DIV3: 793 rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 3; 794 break; 795 case CLKID_FCLK_DIV4: 796 rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 4; 797 break; 798 case CLKID_FCLK_DIV5: 799 rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 5; 800 break; 801 case CLKID_FCLK_DIV7: 802 rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 7; 803 break; 804 case CLKID_MPLL0: 805 case CLKID_MPLL1: 806 case CLKID_MPLL2: 807 rate = meson_mpll_get_rate(clk, id); 808 break; 809 case CLKID_CLK81: 810 rate = meson_clk81_get_rate(clk); 811 break; 812 case CLKID_PCIE_PLL: 813 rate = meson_pcie_pll_get_rate(clk); 814 break; 815 case CLKID_VPU_0: 816 rate = meson_div_get_rate(clk, CLKID_VPU_0_DIV); 817 break; 818 case CLKID_VPU_1: 819 rate = meson_div_get_rate(clk, CLKID_VPU_1_DIV); 820 break; 821 case CLKID_VAPB: 822 rate = meson_mux_get_rate(clk, CLKID_VAPB_SEL); 823 break; 824 case CLKID_VAPB_0: 825 rate = meson_div_get_rate(clk, CLKID_VAPB_0_DIV); 826 break; 827 case CLKID_VAPB_1: 828 rate = meson_div_get_rate(clk, CLKID_VAPB_1_DIV); 829 break; 830 case CLKID_HDMI: 831 rate = meson_div_get_rate(clk, CLKID_HDMI_DIV); 832 break; 833 case CLKID_VPU_0_DIV: 834 case CLKID_VPU_1_DIV: 835 case CLKID_VAPB_0_DIV: 836 case CLKID_VAPB_1_DIV: 837 case CLKID_HDMI_DIV: 838 rate = meson_div_get_rate(clk, id); 839 break; 840 case CLKID_VPU: 841 case CLKID_VPU_0_SEL: 842 case CLKID_VPU_1_SEL: 843 case CLKID_VAPB_SEL: 844 case CLKID_VAPB_0_SEL: 845 case CLKID_VAPB_1_SEL: 846 case CLKID_HDMI_SEL: 847 rate = meson_mux_get_rate(clk, id); 848 break; 849 default: 850 if (gates[id].reg != 0) { 851 /* a clock gate */ 852 rate = meson_clk81_get_rate(clk); 853 break; 854 } 855 return -ENOENT; 856 } 857 858 debug("clock %lu has rate %lu\n", id, rate); 859 return rate; 860} 861 862static ulong meson_clk_get_rate(struct clk *clk) 863{ 864 return meson_clk_get_rate_by_id(clk, clk->id); 865} 866 867static ulong meson_pcie_pll_set_rate(struct clk *clk, ulong rate) 868{ 869 struct meson_clk *priv = dev_get_priv(clk->dev); 870 871 regmap_write(priv->map, HHI_PCIE_PLL_CNTL0, 0x20090496); 872 regmap_write(priv->map, HHI_PCIE_PLL_CNTL0, 0x30090496); 873 regmap_write(priv->map, HHI_PCIE_PLL_CNTL1, 0x00000000); 874 regmap_write(priv->map, HHI_PCIE_PLL_CNTL2, 0x00001100); 875 regmap_write(priv->map, HHI_PCIE_PLL_CNTL3, 0x10058e00); 876 regmap_write(priv->map, HHI_PCIE_PLL_CNTL4, 0x000100c0); 877 regmap_write(priv->map, HHI_PCIE_PLL_CNTL5, 0x68000048); 878 regmap_write(priv->map, HHI_PCIE_PLL_CNTL5, 0x68000068); 879 udelay(20); 880 regmap_write(priv->map, HHI_PCIE_PLL_CNTL4, 0x008100c0); 881 udelay(10); 882 regmap_write(priv->map, HHI_PCIE_PLL_CNTL0, 0x34090496); 883 regmap_write(priv->map, HHI_PCIE_PLL_CNTL0, 0x14090496); 884 udelay(10); 885 regmap_write(priv->map, HHI_PCIE_PLL_CNTL2, 0x00001000); 886 regmap_update_bits(priv->map, HHI_PCIE_PLL_CNTL0, 887 0x1f << 16, 9 << 16); 888 889 return 100000000; 890} 891 892static int meson_clk_set_parent(struct clk *clk, struct clk *parent) 893{ 894 return meson_mux_set_parent(clk, clk->id, parent->id); 895} 896 897static ulong meson_clk_set_rate_by_id(struct clk *clk, unsigned long id, 898 ulong rate, ulong current_rate) 899{ 900 if (current_rate == rate) 901 return 0; 902 903 switch (id) { 904 /* Fixed clocks */ 905 case CLKID_FIXED_PLL: 906 case CLKID_SYS_PLL: 907 case CLKID_FCLK_DIV2: 908 case CLKID_FCLK_DIV3: 909 case CLKID_FCLK_DIV4: 910 case CLKID_FCLK_DIV5: 911 case CLKID_FCLK_DIV7: 912 case CLKID_MPLL0: 913 case CLKID_MPLL1: 914 case CLKID_MPLL2: 915 case CLKID_CLK81: 916 if (current_rate != rate) 917 return -EINVAL; 918 case CLKID_PCIE_PLL: 919 return meson_pcie_pll_set_rate(clk, rate); 920 921 return 0; 922 case CLKID_VPU: 923 return meson_clk_set_rate_by_id(clk, 924 meson_mux_get_parent(clk, CLKID_VPU), rate, 925 current_rate); 926 case CLKID_VAPB: 927 case CLKID_VAPB_SEL: 928 return meson_clk_set_rate_by_id(clk, 929 meson_mux_get_parent(clk, CLKID_VAPB_SEL), 930 rate, current_rate); 931 case CLKID_VPU_0: 932 return meson_div_set_rate(clk, CLKID_VPU_0_DIV, rate, 933 current_rate); 934 case CLKID_VPU_1: 935 return meson_div_set_rate(clk, CLKID_VPU_1_DIV, rate, 936 current_rate); 937 case CLKID_VAPB_0: 938 return meson_div_set_rate(clk, CLKID_VAPB_0_DIV, rate, 939 current_rate); 940 case CLKID_VAPB_1: 941 return meson_div_set_rate(clk, CLKID_VAPB_1_DIV, rate, 942 current_rate); 943 case CLKID_VPU_0_DIV: 944 case CLKID_VPU_1_DIV: 945 case CLKID_VAPB_0_DIV: 946 case CLKID_VAPB_1_DIV: 947 case CLKID_HDMI_DIV: 948 return meson_div_set_rate(clk, id, rate, current_rate); 949 case CLKID_HDMI: 950 return meson_clk_set_rate_by_id(clk, CLKID_HDMI_DIV, 951 rate, current_rate); 952 default: 953 return -ENOENT; 954 } 955 956 return -EINVAL; 957} 958 959static ulong meson_clk_set_rate(struct clk *clk, ulong rate) 960{ 961 ulong current_rate = meson_clk_get_rate_by_id(clk, clk->id); 962 int ret; 963 964 if (IS_ERR_VALUE(current_rate)) 965 return current_rate; 966 967 debug("%s: setting rate of %ld from %ld to %ld\n", 968 __func__, clk->id, current_rate, rate); 969 970 ret = meson_clk_set_rate_by_id(clk, clk->id, rate, current_rate); 971 if (IS_ERR_VALUE(ret)) 972 return ret; 973 974 debug("clock %lu has new rate %lu\n", clk->id, 975 meson_clk_get_rate_by_id(clk, clk->id)); 976 977 return 0; 978} 979 980static int meson_clk_probe(struct udevice *dev) 981{ 982 struct meson_clk *priv = dev_get_priv(dev); 983 984 priv->map = syscon_node_to_regmap(dev_ofnode(dev_get_parent(dev))); 985 if (IS_ERR(priv->map)) 986 return PTR_ERR(priv->map); 987 988 /* 989 * Depending on the boot src, the state of the MMC clock might 990 * be different. Reset it to make sure we won't get stuck 991 */ 992 regmap_write(priv->map, HHI_NAND_CLK_CNTL, 0); 993 regmap_write(priv->map, HHI_SD_EMMC_CLK_CNTL, 0); 994 995 debug("meson-clk-g12a: probed\n"); 996 997 return 0; 998} 999 1000static struct clk_ops meson_clk_ops = { 1001 .disable = meson_clk_disable, 1002 .enable = meson_clk_enable, 1003 .get_rate = meson_clk_get_rate, 1004 .set_parent = meson_clk_set_parent, 1005 .set_rate = meson_clk_set_rate, 1006}; 1007 1008static const struct udevice_id meson_clk_ids[] = { 1009 { .compatible = "amlogic,g12a-clkc" }, 1010 { .compatible = "amlogic,g12b-clkc" }, 1011 { .compatible = "amlogic,sm1-clkc" }, 1012 { } 1013}; 1014 1015U_BOOT_DRIVER(meson_clk_g12a) = { 1016 .name = "meson_clk_g12a", 1017 .id = UCLASS_CLK, 1018 .of_match = meson_clk_ids, 1019 .priv_auto = sizeof(struct meson_clk), 1020 .ops = &meson_clk_ops, 1021 .probe = meson_clk_probe, 1022}; 1023