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