565 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * X1000 SoC CGU driver4 * Copyright (c) 2019 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>5 */6 7#include <linux/clk-provider.h>8#include <linux/delay.h>9#include <linux/io.h>10#include <linux/of.h>11#include <linux/rational.h>12 13#include <dt-bindings/clock/ingenic,x1000-cgu.h>14 15#include "cgu.h"16#include "pm.h"17 18/* CGU register offsets */19#define CGU_REG_CPCCR 0x0020#define CGU_REG_APLL 0x1021#define CGU_REG_MPLL 0x1422#define CGU_REG_CLKGR 0x2023#define CGU_REG_OPCR 0x2424#define CGU_REG_DDRCDR 0x2c25#define CGU_REG_USBPCR 0x3c26#define CGU_REG_USBPCR1 0x4827#define CGU_REG_USBCDR 0x5028#define CGU_REG_MACCDR 0x5429#define CGU_REG_I2SCDR 0x6030#define CGU_REG_LPCDR 0x6431#define CGU_REG_MSC0CDR 0x6832#define CGU_REG_I2SCDR1 0x7033#define CGU_REG_SSICDR 0x7434#define CGU_REG_CIMCDR 0x7c35#define CGU_REG_PCMCDR 0x8436#define CGU_REG_MSC1CDR 0xa437#define CGU_REG_CMP_INTR 0xb038#define CGU_REG_CMP_INTRE 0xb439#define CGU_REG_DRCG 0xd040#define CGU_REG_CPCSR 0xd441#define CGU_REG_PCMCDR1 0xe042#define CGU_REG_MACPHYC 0xe843 44/* bits within the OPCR register */45#define OPCR_SPENDN0 BIT(7)46#define OPCR_SPENDN1 BIT(6)47 48/* bits within the USBPCR register */49#define USBPCR_SIDDQ BIT(21)50#define USBPCR_OTG_DISABLE BIT(20)51 52/* bits within the USBPCR1 register */53#define USBPCR1_REFCLKSEL_SHIFT 2654#define USBPCR1_REFCLKSEL_MASK (0x3 << USBPCR1_REFCLKSEL_SHIFT)55#define USBPCR1_REFCLKSEL_CORE (0x2 << USBPCR1_REFCLKSEL_SHIFT)56#define USBPCR1_REFCLKDIV_SHIFT 2457#define USBPCR1_REFCLKDIV_MASK (0x3 << USBPCR1_REFCLKDIV_SHIFT)58#define USBPCR1_REFCLKDIV_48 (0x2 << USBPCR1_REFCLKDIV_SHIFT)59#define USBPCR1_REFCLKDIV_24 (0x1 << USBPCR1_REFCLKDIV_SHIFT)60#define USBPCR1_REFCLKDIV_12 (0x0 << USBPCR1_REFCLKDIV_SHIFT)61 62static struct ingenic_cgu *cgu;63 64static unsigned long x1000_otg_phy_recalc_rate(struct clk_hw *hw,65 unsigned long parent_rate)66{67 u32 usbpcr1;68 unsigned refclk_div;69 70 usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);71 refclk_div = usbpcr1 & USBPCR1_REFCLKDIV_MASK;72 73 switch (refclk_div) {74 case USBPCR1_REFCLKDIV_12:75 return 12000000;76 77 case USBPCR1_REFCLKDIV_24:78 return 24000000;79 80 case USBPCR1_REFCLKDIV_48:81 return 48000000;82 }83 84 return parent_rate;85}86 87static long x1000_otg_phy_round_rate(struct clk_hw *hw, unsigned long req_rate,88 unsigned long *parent_rate)89{90 if (req_rate < 18000000)91 return 12000000;92 93 if (req_rate < 36000000)94 return 24000000;95 96 return 48000000;97}98 99static int x1000_otg_phy_set_rate(struct clk_hw *hw, unsigned long req_rate,100 unsigned long parent_rate)101{102 unsigned long flags;103 u32 usbpcr1, div_bits;104 105 switch (req_rate) {106 case 12000000:107 div_bits = USBPCR1_REFCLKDIV_12;108 break;109 110 case 24000000:111 div_bits = USBPCR1_REFCLKDIV_24;112 break;113 114 case 48000000:115 div_bits = USBPCR1_REFCLKDIV_48;116 break;117 118 default:119 return -EINVAL;120 }121 122 spin_lock_irqsave(&cgu->lock, flags);123 124 usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);125 usbpcr1 &= ~USBPCR1_REFCLKDIV_MASK;126 usbpcr1 |= div_bits;127 writel(usbpcr1, cgu->base + CGU_REG_USBPCR1);128 129 spin_unlock_irqrestore(&cgu->lock, flags);130 return 0;131}132 133static int x1000_usb_phy_enable(struct clk_hw *hw)134{135 void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;136 void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR;137 138 writel(readl(reg_opcr) | OPCR_SPENDN0, reg_opcr);139 writel(readl(reg_usbpcr) & ~USBPCR_OTG_DISABLE & ~USBPCR_SIDDQ, reg_usbpcr);140 return 0;141}142 143static void x1000_usb_phy_disable(struct clk_hw *hw)144{145 void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;146 void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR;147 148 writel(readl(reg_opcr) & ~OPCR_SPENDN0, reg_opcr);149 writel(readl(reg_usbpcr) | USBPCR_OTG_DISABLE | USBPCR_SIDDQ, reg_usbpcr);150}151 152static int x1000_usb_phy_is_enabled(struct clk_hw *hw)153{154 void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;155 void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR;156 157 return (readl(reg_opcr) & OPCR_SPENDN0) &&158 !(readl(reg_usbpcr) & USBPCR_SIDDQ) &&159 !(readl(reg_usbpcr) & USBPCR_OTG_DISABLE);160}161 162static const struct clk_ops x1000_otg_phy_ops = {163 .recalc_rate = x1000_otg_phy_recalc_rate,164 .round_rate = x1000_otg_phy_round_rate,165 .set_rate = x1000_otg_phy_set_rate,166 167 .enable = x1000_usb_phy_enable,168 .disable = x1000_usb_phy_disable,169 .is_enabled = x1000_usb_phy_is_enabled,170};171 172static void173x1000_i2spll_calc_m_n_od(const struct ingenic_cgu_pll_info *pll_info,174 unsigned long rate, unsigned long parent_rate,175 unsigned int *pm, unsigned int *pn, unsigned int *pod)176{177 const unsigned long m_max = GENMASK(pll_info->m_bits - 1, 0);178 const unsigned long n_max = GENMASK(pll_info->n_bits - 1, 0);179 unsigned long m, n;180 181 rational_best_approximation(rate, parent_rate, m_max, n_max, &m, &n);182 183 /* n should not be less than 2*m */184 if (n < 2 * m)185 n = 2 * m;186 187 *pm = m;188 *pn = n;189 *pod = 1;190}191 192static void193x1000_i2spll_set_rate_hook(const struct ingenic_cgu_pll_info *pll_info,194 unsigned long rate, unsigned long parent_rate)195{196 /*197 * Writing 0 causes I2SCDR1.I2SDIV_D to be automatically recalculated198 * based on the current value of I2SCDR.I2SDIV_N, which is needed for199 * the divider to function correctly.200 */201 writel(0, cgu->base + CGU_REG_I2SCDR1);202}203 204static const s8 pll_od_encoding[8] = {205 0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3,206};207 208static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {209 210 /* External clocks */211 212 [X1000_CLK_EXCLK] = { "ext", CGU_CLK_EXT },213 [X1000_CLK_RTCLK] = { "rtc", CGU_CLK_EXT },214 215 /* PLLs */216 217 [X1000_CLK_APLL] = {218 "apll", CGU_CLK_PLL,219 .parents = { X1000_CLK_EXCLK },220 .pll = {221 .reg = CGU_REG_APLL,222 .rate_multiplier = 1,223 .m_shift = 24,224 .m_bits = 7,225 .m_offset = 1,226 .n_shift = 18,227 .n_bits = 5,228 .n_offset = 1,229 .od_shift = 16,230 .od_bits = 2,231 .od_max = 8,232 .od_encoding = pll_od_encoding,233 .bypass_reg = CGU_REG_APLL,234 .bypass_bit = 9,235 .enable_bit = 8,236 .stable_bit = 10,237 },238 },239 240 [X1000_CLK_MPLL] = {241 "mpll", CGU_CLK_PLL,242 .parents = { X1000_CLK_EXCLK },243 .pll = {244 .reg = CGU_REG_MPLL,245 .rate_multiplier = 1,246 .m_shift = 24,247 .m_bits = 7,248 .m_offset = 1,249 .n_shift = 18,250 .n_bits = 5,251 .n_offset = 1,252 .od_shift = 16,253 .od_bits = 2,254 .od_max = 8,255 .od_encoding = pll_od_encoding,256 .bypass_reg = CGU_REG_MPLL,257 .bypass_bit = 6,258 .enable_bit = 7,259 .stable_bit = 0,260 },261 },262 263 /* Custom (SoC-specific) OTG PHY */264 265 [X1000_CLK_OTGPHY] = {266 "otg_phy", CGU_CLK_CUSTOM,267 .parents = { -1, -1, X1000_CLK_EXCLK, -1 },268 .custom = { &x1000_otg_phy_ops },269 },270 271 /* Muxes & dividers */272 273 [X1000_CLK_SCLKA] = {274 "sclk_a", CGU_CLK_MUX,275 .parents = { -1, X1000_CLK_EXCLK, X1000_CLK_APLL, -1 },276 .mux = { CGU_REG_CPCCR, 30, 2 },277 },278 279 [X1000_CLK_CPUMUX] = {280 "cpu_mux", CGU_CLK_MUX,281 .parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 },282 .mux = { CGU_REG_CPCCR, 28, 2 },283 },284 285 [X1000_CLK_CPU] = {286 "cpu", CGU_CLK_DIV | CGU_CLK_GATE,287 /*288 * Disabling the CPU clock or any parent clocks will hang the289 * system; mark it critical.290 */291 .flags = CLK_IS_CRITICAL,292 .parents = { X1000_CLK_CPUMUX },293 .div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1 },294 .gate = { CGU_REG_CLKGR, 30 },295 },296 297 [X1000_CLK_L2CACHE] = {298 "l2cache", CGU_CLK_DIV,299 /*300 * The L2 cache clock is critical if caches are enabled and301 * disabling it or any parent clocks will hang the system.302 */303 .flags = CLK_IS_CRITICAL,304 .parents = { X1000_CLK_CPUMUX },305 .div = { CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1 },306 },307 308 [X1000_CLK_AHB0] = {309 "ahb0", CGU_CLK_MUX | CGU_CLK_DIV,310 .parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 },311 .mux = { CGU_REG_CPCCR, 26, 2 },312 .div = { CGU_REG_CPCCR, 8, 1, 4, 21, -1, -1 },313 },314 315 [X1000_CLK_AHB2PMUX] = {316 "ahb2_apb_mux", CGU_CLK_MUX,317 .parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 },318 .mux = { CGU_REG_CPCCR, 24, 2 },319 },320 321 [X1000_CLK_AHB2] = {322 "ahb2", CGU_CLK_DIV,323 .parents = { X1000_CLK_AHB2PMUX },324 .div = { CGU_REG_CPCCR, 12, 1, 4, 20, -1, -1 },325 },326 327 [X1000_CLK_PCLK] = {328 "pclk", CGU_CLK_DIV | CGU_CLK_GATE,329 .parents = { X1000_CLK_AHB2PMUX },330 .div = { CGU_REG_CPCCR, 16, 1, 4, 20, -1, -1 },331 .gate = { CGU_REG_CLKGR, 28 },332 },333 334 [X1000_CLK_DDR] = {335 "ddr", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,336 /*337 * Disabling DDR clock or its parents will render DRAM338 * inaccessible; mark it critical.339 */340 .flags = CLK_IS_CRITICAL,341 .parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 },342 .mux = { CGU_REG_DDRCDR, 30, 2 },343 .div = { CGU_REG_DDRCDR, 0, 1, 4, 29, 28, 27 },344 .gate = { CGU_REG_CLKGR, 31 },345 },346 347 [X1000_CLK_MAC] = {348 "mac", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,349 .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL },350 .mux = { CGU_REG_MACCDR, 31, 1 },351 .div = { CGU_REG_MACCDR, 0, 1, 8, 29, 28, 27 },352 .gate = { CGU_REG_CLKGR, 25 },353 },354 355 [X1000_CLK_I2SPLLMUX] = {356 "i2s_pll_mux", CGU_CLK_MUX,357 .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL },358 .mux = { CGU_REG_I2SCDR, 31, 1 },359 },360 361 [X1000_CLK_I2SPLL] = {362 "i2s_pll", CGU_CLK_PLL,363 .parents = { X1000_CLK_I2SPLLMUX },364 .pll = {365 .reg = CGU_REG_I2SCDR,366 .rate_multiplier = 1,367 .m_shift = 13,368 .m_bits = 9,369 .n_shift = 0,370 .n_bits = 13,371 .calc_m_n_od = x1000_i2spll_calc_m_n_od,372 .set_rate_hook = x1000_i2spll_set_rate_hook,373 },374 },375 376 [X1000_CLK_I2S] = {377 "i2s", CGU_CLK_MUX,378 .parents = { X1000_CLK_EXCLK, -1, -1, X1000_CLK_I2SPLL },379 /*380 * NOTE: the mux is at bit 30; bit 29 enables the M/N divider.381 * Therefore, the divider is disabled when EXCLK is selected.382 */383 .mux = { CGU_REG_I2SCDR, 29, 2 },384 },385 386 [X1000_CLK_LCD] = {387 "lcd", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,388 .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL },389 .mux = { CGU_REG_LPCDR, 31, 1 },390 .div = { CGU_REG_LPCDR, 0, 1, 8, 28, 27, 26 },391 .gate = { CGU_REG_CLKGR, 23 },392 },393 394 [X1000_CLK_MSCMUX] = {395 "msc_mux", CGU_CLK_MUX,396 .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL },397 .mux = { CGU_REG_MSC0CDR, 31, 1 },398 },399 400 [X1000_CLK_MSC0] = {401 "msc0", CGU_CLK_DIV | CGU_CLK_GATE,402 .parents = { X1000_CLK_MSCMUX },403 .div = { CGU_REG_MSC0CDR, 0, 2, 8, 29, 28, 27 },404 .gate = { CGU_REG_CLKGR, 4 },405 },406 407 [X1000_CLK_MSC1] = {408 "msc1", CGU_CLK_DIV | CGU_CLK_GATE,409 .parents = { X1000_CLK_MSCMUX, -1, -1, -1 },410 .div = { CGU_REG_MSC1CDR, 0, 2, 8, 29, 28, 27 },411 .gate = { CGU_REG_CLKGR, 5 },412 },413 414 [X1000_CLK_OTG] = {415 "otg", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,416 .parents = { X1000_CLK_EXCLK, -1, X1000_CLK_APLL, X1000_CLK_MPLL },417 .mux = { CGU_REG_USBCDR, 30, 2 },418 .div = { CGU_REG_USBCDR, 0, 1, 8, 29, 28, 27 },419 .gate = { CGU_REG_CLKGR, 3 },420 },421 422 [X1000_CLK_SSIPLL] = {423 "ssi_pll", CGU_CLK_MUX | CGU_CLK_DIV,424 .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL },425 .mux = { CGU_REG_SSICDR, 31, 1 },426 .div = { CGU_REG_SSICDR, 0, 1, 8, 29, 28, 27 },427 },428 429 [X1000_CLK_SSIPLL_DIV2] = {430 "ssi_pll_div2", CGU_CLK_FIXDIV,431 .parents = { X1000_CLK_SSIPLL },432 .fixdiv = { 2 },433 },434 435 [X1000_CLK_SSIMUX] = {436 "ssi_mux", CGU_CLK_MUX,437 .parents = { X1000_CLK_EXCLK, X1000_CLK_SSIPLL_DIV2 },438 .mux = { CGU_REG_SSICDR, 30, 1 },439 },440 441 [X1000_CLK_EXCLK_DIV512] = {442 "exclk_div512", CGU_CLK_FIXDIV,443 .parents = { X1000_CLK_EXCLK },444 .fixdiv = { 512 },445 },446 447 [X1000_CLK_RTC] = {448 "rtc_ercs", CGU_CLK_MUX | CGU_CLK_GATE,449 .parents = { X1000_CLK_EXCLK_DIV512, X1000_CLK_RTCLK },450 .mux = { CGU_REG_OPCR, 2, 1},451 .gate = { CGU_REG_CLKGR, 27 },452 },453 454 /* Gate-only clocks */455 456 [X1000_CLK_EMC] = {457 "emc", CGU_CLK_GATE,458 .parents = { X1000_CLK_AHB2 },459 .gate = { CGU_REG_CLKGR, 0 },460 },461 462 [X1000_CLK_EFUSE] = {463 "efuse", CGU_CLK_GATE,464 .parents = { X1000_CLK_AHB2 },465 .gate = { CGU_REG_CLKGR, 1 },466 },467 468 [X1000_CLK_SFC] = {469 "sfc", CGU_CLK_GATE,470 .parents = { X1000_CLK_SSIPLL },471 .gate = { CGU_REG_CLKGR, 2 },472 },473 474 [X1000_CLK_I2C0] = {475 "i2c0", CGU_CLK_GATE,476 .parents = { X1000_CLK_PCLK },477 .gate = { CGU_REG_CLKGR, 7 },478 },479 480 [X1000_CLK_I2C1] = {481 "i2c1", CGU_CLK_GATE,482 .parents = { X1000_CLK_PCLK },483 .gate = { CGU_REG_CLKGR, 8 },484 },485 486 [X1000_CLK_I2C2] = {487 "i2c2", CGU_CLK_GATE,488 .parents = { X1000_CLK_PCLK },489 .gate = { CGU_REG_CLKGR, 9 },490 },491 492 [X1000_CLK_AIC] = {493 "aic", CGU_CLK_GATE,494 .parents = { X1000_CLK_EXCLK },495 .gate = { CGU_REG_CLKGR, 11 },496 },497 498 [X1000_CLK_UART0] = {499 "uart0", CGU_CLK_GATE,500 .parents = { X1000_CLK_EXCLK },501 .gate = { CGU_REG_CLKGR, 14 },502 },503 504 [X1000_CLK_UART1] = {505 "uart1", CGU_CLK_GATE,506 .parents = { X1000_CLK_EXCLK},507 .gate = { CGU_REG_CLKGR, 15 },508 },509 510 [X1000_CLK_UART2] = {511 "uart2", CGU_CLK_GATE,512 .parents = { X1000_CLK_EXCLK },513 .gate = { CGU_REG_CLKGR, 16 },514 },515 516 [X1000_CLK_TCU] = {517 "tcu", CGU_CLK_GATE,518 .parents = { X1000_CLK_EXCLK },519 .gate = { CGU_REG_CLKGR, 18 },520 },521 522 [X1000_CLK_SSI] = {523 "ssi", CGU_CLK_GATE,524 .parents = { X1000_CLK_SSIMUX },525 .gate = { CGU_REG_CLKGR, 19 },526 },527 528 [X1000_CLK_OST] = {529 "ost", CGU_CLK_GATE,530 .parents = { X1000_CLK_EXCLK },531 .gate = { CGU_REG_CLKGR, 20 },532 },533 534 [X1000_CLK_PDMA] = {535 "pdma", CGU_CLK_GATE,536 .parents = { X1000_CLK_EXCLK },537 .gate = { CGU_REG_CLKGR, 21 },538 },539};540 541static void __init x1000_cgu_init(struct device_node *np)542{543 int retval;544 545 cgu = ingenic_cgu_new(x1000_cgu_clocks,546 ARRAY_SIZE(x1000_cgu_clocks), np);547 if (!cgu) {548 pr_err("%s: failed to initialise CGU\n", __func__);549 return;550 }551 552 retval = ingenic_cgu_register_clocks(cgu);553 if (retval) {554 pr_err("%s: failed to register CGU Clocks\n", __func__);555 return;556 }557 558 ingenic_cgu_register_syscore_ops(cgu);559}560/*561 * CGU has some children devices, this is useful for probing children devices562 * in the case where the device node is compatible with "simple-mfd".563 */564CLK_OF_DECLARE_DRIVER(x1000_cgu, "ingenic,x1000-cgu", x1000_cgu_init);565