x1000-cgu.c (12102B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * X1000 SoC CGU driver 4 * 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 12#include <dt-bindings/clock/ingenic,x1000-cgu.h> 13 14#include "cgu.h" 15#include "pm.h" 16 17/* CGU register offsets */ 18#define CGU_REG_CPCCR 0x00 19#define CGU_REG_APLL 0x10 20#define CGU_REG_MPLL 0x14 21#define CGU_REG_CLKGR 0x20 22#define CGU_REG_OPCR 0x24 23#define CGU_REG_DDRCDR 0x2c 24#define CGU_REG_USBPCR 0x3c 25#define CGU_REG_USBPCR1 0x48 26#define CGU_REG_USBCDR 0x50 27#define CGU_REG_MACCDR 0x54 28#define CGU_REG_I2SCDR 0x60 29#define CGU_REG_LPCDR 0x64 30#define CGU_REG_MSC0CDR 0x68 31#define CGU_REG_I2SCDR1 0x70 32#define CGU_REG_SSICDR 0x74 33#define CGU_REG_CIMCDR 0x7c 34#define CGU_REG_PCMCDR 0x84 35#define CGU_REG_MSC1CDR 0xa4 36#define CGU_REG_CMP_INTR 0xb0 37#define CGU_REG_CMP_INTRE 0xb4 38#define CGU_REG_DRCG 0xd0 39#define CGU_REG_CPCSR 0xd4 40#define CGU_REG_PCMCDR1 0xe0 41#define CGU_REG_MACPHYC 0xe8 42 43/* bits within the OPCR register */ 44#define OPCR_SPENDN0 BIT(7) 45#define OPCR_SPENDN1 BIT(6) 46 47/* bits within the USBPCR register */ 48#define USBPCR_SIDDQ BIT(21) 49#define USBPCR_OTG_DISABLE BIT(20) 50 51/* bits within the USBPCR1 register */ 52#define USBPCR1_REFCLKSEL_SHIFT 26 53#define USBPCR1_REFCLKSEL_MASK (0x3 << USBPCR1_REFCLKSEL_SHIFT) 54#define USBPCR1_REFCLKSEL_CORE (0x2 << USBPCR1_REFCLKSEL_SHIFT) 55#define USBPCR1_REFCLKDIV_SHIFT 24 56#define USBPCR1_REFCLKDIV_MASK (0x3 << USBPCR1_REFCLKDIV_SHIFT) 57#define USBPCR1_REFCLKDIV_48 (0x2 << USBPCR1_REFCLKDIV_SHIFT) 58#define USBPCR1_REFCLKDIV_24 (0x1 << USBPCR1_REFCLKDIV_SHIFT) 59#define USBPCR1_REFCLKDIV_12 (0x0 << USBPCR1_REFCLKDIV_SHIFT) 60 61static struct ingenic_cgu *cgu; 62 63static unsigned long x1000_otg_phy_recalc_rate(struct clk_hw *hw, 64 unsigned long parent_rate) 65{ 66 u32 usbpcr1; 67 unsigned refclk_div; 68 69 usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1); 70 refclk_div = usbpcr1 & USBPCR1_REFCLKDIV_MASK; 71 72 switch (refclk_div) { 73 case USBPCR1_REFCLKDIV_12: 74 return 12000000; 75 76 case USBPCR1_REFCLKDIV_24: 77 return 24000000; 78 79 case USBPCR1_REFCLKDIV_48: 80 return 48000000; 81 } 82 83 return parent_rate; 84} 85 86static long x1000_otg_phy_round_rate(struct clk_hw *hw, unsigned long req_rate, 87 unsigned long *parent_rate) 88{ 89 if (req_rate < 18000000) 90 return 12000000; 91 92 if (req_rate < 36000000) 93 return 24000000; 94 95 return 48000000; 96} 97 98static int x1000_otg_phy_set_rate(struct clk_hw *hw, unsigned long req_rate, 99 unsigned long parent_rate) 100{ 101 unsigned long flags; 102 u32 usbpcr1, div_bits; 103 104 switch (req_rate) { 105 case 12000000: 106 div_bits = USBPCR1_REFCLKDIV_12; 107 break; 108 109 case 24000000: 110 div_bits = USBPCR1_REFCLKDIV_24; 111 break; 112 113 case 48000000: 114 div_bits = USBPCR1_REFCLKDIV_48; 115 break; 116 117 default: 118 return -EINVAL; 119 } 120 121 spin_lock_irqsave(&cgu->lock, flags); 122 123 usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1); 124 usbpcr1 &= ~USBPCR1_REFCLKDIV_MASK; 125 usbpcr1 |= div_bits; 126 writel(usbpcr1, cgu->base + CGU_REG_USBPCR1); 127 128 spin_unlock_irqrestore(&cgu->lock, flags); 129 return 0; 130} 131 132static int x1000_usb_phy_enable(struct clk_hw *hw) 133{ 134 void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR; 135 void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR; 136 137 writel(readl(reg_opcr) | OPCR_SPENDN0, reg_opcr); 138 writel(readl(reg_usbpcr) & ~USBPCR_OTG_DISABLE & ~USBPCR_SIDDQ, reg_usbpcr); 139 return 0; 140} 141 142static void x1000_usb_phy_disable(struct clk_hw *hw) 143{ 144 void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR; 145 void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR; 146 147 writel(readl(reg_opcr) & ~OPCR_SPENDN0, reg_opcr); 148 writel(readl(reg_usbpcr) | USBPCR_OTG_DISABLE | USBPCR_SIDDQ, reg_usbpcr); 149} 150 151static int x1000_usb_phy_is_enabled(struct clk_hw *hw) 152{ 153 void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR; 154 void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR; 155 156 return (readl(reg_opcr) & OPCR_SPENDN0) && 157 !(readl(reg_usbpcr) & USBPCR_SIDDQ) && 158 !(readl(reg_usbpcr) & USBPCR_OTG_DISABLE); 159} 160 161static const struct clk_ops x1000_otg_phy_ops = { 162 .recalc_rate = x1000_otg_phy_recalc_rate, 163 .round_rate = x1000_otg_phy_round_rate, 164 .set_rate = x1000_otg_phy_set_rate, 165 166 .enable = x1000_usb_phy_enable, 167 .disable = x1000_usb_phy_disable, 168 .is_enabled = x1000_usb_phy_is_enabled, 169}; 170 171static const s8 pll_od_encoding[8] = { 172 0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3, 173}; 174 175static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = { 176 177 /* External clocks */ 178 179 [X1000_CLK_EXCLK] = { "ext", CGU_CLK_EXT }, 180 [X1000_CLK_RTCLK] = { "rtc", CGU_CLK_EXT }, 181 182 /* PLLs */ 183 184 [X1000_CLK_APLL] = { 185 "apll", CGU_CLK_PLL, 186 .parents = { X1000_CLK_EXCLK, -1, -1, -1 }, 187 .pll = { 188 .reg = CGU_REG_APLL, 189 .rate_multiplier = 1, 190 .m_shift = 24, 191 .m_bits = 7, 192 .m_offset = 1, 193 .n_shift = 18, 194 .n_bits = 5, 195 .n_offset = 1, 196 .od_shift = 16, 197 .od_bits = 2, 198 .od_max = 8, 199 .od_encoding = pll_od_encoding, 200 .bypass_reg = CGU_REG_APLL, 201 .bypass_bit = 9, 202 .enable_bit = 8, 203 .stable_bit = 10, 204 }, 205 }, 206 207 [X1000_CLK_MPLL] = { 208 "mpll", CGU_CLK_PLL, 209 .parents = { X1000_CLK_EXCLK, -1, -1, -1 }, 210 .pll = { 211 .reg = CGU_REG_MPLL, 212 .rate_multiplier = 1, 213 .m_shift = 24, 214 .m_bits = 7, 215 .m_offset = 1, 216 .n_shift = 18, 217 .n_bits = 5, 218 .n_offset = 1, 219 .od_shift = 16, 220 .od_bits = 2, 221 .od_max = 8, 222 .od_encoding = pll_od_encoding, 223 .bypass_reg = CGU_REG_MPLL, 224 .bypass_bit = 6, 225 .enable_bit = 7, 226 .stable_bit = 0, 227 }, 228 }, 229 230 /* Custom (SoC-specific) OTG PHY */ 231 232 [X1000_CLK_OTGPHY] = { 233 "otg_phy", CGU_CLK_CUSTOM, 234 .parents = { -1, -1, X1000_CLK_EXCLK, -1 }, 235 .custom = { &x1000_otg_phy_ops }, 236 }, 237 238 /* Muxes & dividers */ 239 240 [X1000_CLK_SCLKA] = { 241 "sclk_a", CGU_CLK_MUX, 242 .parents = { -1, X1000_CLK_EXCLK, X1000_CLK_APLL, -1 }, 243 .mux = { CGU_REG_CPCCR, 30, 2 }, 244 }, 245 246 [X1000_CLK_CPUMUX] = { 247 "cpu_mux", CGU_CLK_MUX, 248 .parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 }, 249 .mux = { CGU_REG_CPCCR, 28, 2 }, 250 }, 251 252 [X1000_CLK_CPU] = { 253 "cpu", CGU_CLK_DIV | CGU_CLK_GATE, 254 /* 255 * Disabling the CPU clock or any parent clocks will hang the 256 * system; mark it critical. 257 */ 258 .flags = CLK_IS_CRITICAL, 259 .parents = { X1000_CLK_CPUMUX, -1, -1, -1 }, 260 .div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1 }, 261 .gate = { CGU_REG_CLKGR, 30 }, 262 }, 263 264 [X1000_CLK_L2CACHE] = { 265 "l2cache", CGU_CLK_DIV, 266 /* 267 * The L2 cache clock is critical if caches are enabled and 268 * disabling it or any parent clocks will hang the system. 269 */ 270 .flags = CLK_IS_CRITICAL, 271 .parents = { X1000_CLK_CPUMUX, -1, -1, -1 }, 272 .div = { CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1 }, 273 }, 274 275 [X1000_CLK_AHB0] = { 276 "ahb0", CGU_CLK_MUX | CGU_CLK_DIV, 277 .parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 }, 278 .mux = { CGU_REG_CPCCR, 26, 2 }, 279 .div = { CGU_REG_CPCCR, 8, 1, 4, 21, -1, -1 }, 280 }, 281 282 [X1000_CLK_AHB2PMUX] = { 283 "ahb2_apb_mux", CGU_CLK_MUX, 284 .parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 }, 285 .mux = { CGU_REG_CPCCR, 24, 2 }, 286 }, 287 288 [X1000_CLK_AHB2] = { 289 "ahb2", CGU_CLK_DIV, 290 .parents = { X1000_CLK_AHB2PMUX, -1, -1, -1 }, 291 .div = { CGU_REG_CPCCR, 12, 1, 4, 20, -1, -1 }, 292 }, 293 294 [X1000_CLK_PCLK] = { 295 "pclk", CGU_CLK_DIV | CGU_CLK_GATE, 296 .parents = { X1000_CLK_AHB2PMUX, -1, -1, -1 }, 297 .div = { CGU_REG_CPCCR, 16, 1, 4, 20, -1, -1 }, 298 .gate = { CGU_REG_CLKGR, 28 }, 299 }, 300 301 [X1000_CLK_DDR] = { 302 "ddr", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE, 303 /* 304 * Disabling DDR clock or its parents will render DRAM 305 * inaccessible; mark it critical. 306 */ 307 .flags = CLK_IS_CRITICAL, 308 .parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 }, 309 .mux = { CGU_REG_DDRCDR, 30, 2 }, 310 .div = { CGU_REG_DDRCDR, 0, 1, 4, 29, 28, 27 }, 311 .gate = { CGU_REG_CLKGR, 31 }, 312 }, 313 314 [X1000_CLK_MAC] = { 315 "mac", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE, 316 .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL }, 317 .mux = { CGU_REG_MACCDR, 31, 1 }, 318 .div = { CGU_REG_MACCDR, 0, 1, 8, 29, 28, 27 }, 319 .gate = { CGU_REG_CLKGR, 25 }, 320 }, 321 322 [X1000_CLK_LCD] = { 323 "lcd", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE, 324 .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL }, 325 .mux = { CGU_REG_LPCDR, 31, 1 }, 326 .div = { CGU_REG_LPCDR, 0, 1, 8, 28, 27, 26 }, 327 .gate = { CGU_REG_CLKGR, 23 }, 328 }, 329 330 [X1000_CLK_MSCMUX] = { 331 "msc_mux", CGU_CLK_MUX, 332 .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL}, 333 .mux = { CGU_REG_MSC0CDR, 31, 1 }, 334 }, 335 336 [X1000_CLK_MSC0] = { 337 "msc0", CGU_CLK_DIV | CGU_CLK_GATE, 338 .parents = { X1000_CLK_MSCMUX, -1, -1, -1 }, 339 .div = { CGU_REG_MSC0CDR, 0, 2, 8, 29, 28, 27 }, 340 .gate = { CGU_REG_CLKGR, 4 }, 341 }, 342 343 [X1000_CLK_MSC1] = { 344 "msc1", CGU_CLK_DIV | CGU_CLK_GATE, 345 .parents = { X1000_CLK_MSCMUX, -1, -1, -1 }, 346 .div = { CGU_REG_MSC1CDR, 0, 2, 8, 29, 28, 27 }, 347 .gate = { CGU_REG_CLKGR, 5 }, 348 }, 349 350 [X1000_CLK_OTG] = { 351 "otg", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, 352 .parents = { X1000_CLK_EXCLK, -1, 353 X1000_CLK_APLL, X1000_CLK_MPLL }, 354 .mux = { CGU_REG_USBCDR, 30, 2 }, 355 .div = { CGU_REG_USBCDR, 0, 1, 8, 29, 28, 27 }, 356 .gate = { CGU_REG_CLKGR, 3 }, 357 }, 358 359 [X1000_CLK_SSIPLL] = { 360 "ssi_pll", CGU_CLK_MUX | CGU_CLK_DIV, 361 .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL, -1, -1 }, 362 .mux = { CGU_REG_SSICDR, 31, 1 }, 363 .div = { CGU_REG_SSICDR, 0, 1, 8, 29, 28, 27 }, 364 }, 365 366 [X1000_CLK_SSIPLL_DIV2] = { 367 "ssi_pll_div2", CGU_CLK_FIXDIV, 368 .parents = { X1000_CLK_SSIPLL }, 369 .fixdiv = { 2 }, 370 }, 371 372 [X1000_CLK_SSIMUX] = { 373 "ssi_mux", CGU_CLK_MUX, 374 .parents = { X1000_CLK_EXCLK, X1000_CLK_SSIPLL_DIV2, -1, -1 }, 375 .mux = { CGU_REG_SSICDR, 30, 1 }, 376 }, 377 378 [X1000_CLK_EXCLK_DIV512] = { 379 "exclk_div512", CGU_CLK_FIXDIV, 380 .parents = { X1000_CLK_EXCLK }, 381 .fixdiv = { 512 }, 382 }, 383 384 [X1000_CLK_RTC] = { 385 "rtc_ercs", CGU_CLK_MUX | CGU_CLK_GATE, 386 .parents = { X1000_CLK_EXCLK_DIV512, X1000_CLK_RTCLK }, 387 .mux = { CGU_REG_OPCR, 2, 1}, 388 .gate = { CGU_REG_CLKGR, 27 }, 389 }, 390 391 /* Gate-only clocks */ 392 393 [X1000_CLK_EMC] = { 394 "emc", CGU_CLK_GATE, 395 .parents = { X1000_CLK_AHB2, -1, -1, -1 }, 396 .gate = { CGU_REG_CLKGR, 0 }, 397 }, 398 399 [X1000_CLK_EFUSE] = { 400 "efuse", CGU_CLK_GATE, 401 .parents = { X1000_CLK_AHB2, -1, -1, -1 }, 402 .gate = { CGU_REG_CLKGR, 1 }, 403 }, 404 405 [X1000_CLK_SFC] = { 406 "sfc", CGU_CLK_GATE, 407 .parents = { X1000_CLK_SSIPLL, -1, -1, -1 }, 408 .gate = { CGU_REG_CLKGR, 2 }, 409 }, 410 411 [X1000_CLK_I2C0] = { 412 "i2c0", CGU_CLK_GATE, 413 .parents = { X1000_CLK_PCLK, -1, -1, -1 }, 414 .gate = { CGU_REG_CLKGR, 7 }, 415 }, 416 417 [X1000_CLK_I2C1] = { 418 "i2c1", CGU_CLK_GATE, 419 .parents = { X1000_CLK_PCLK, -1, -1, -1 }, 420 .gate = { CGU_REG_CLKGR, 8 }, 421 }, 422 423 [X1000_CLK_I2C2] = { 424 "i2c2", CGU_CLK_GATE, 425 .parents = { X1000_CLK_PCLK, -1, -1, -1 }, 426 .gate = { CGU_REG_CLKGR, 9 }, 427 }, 428 429 [X1000_CLK_UART0] = { 430 "uart0", CGU_CLK_GATE, 431 .parents = { X1000_CLK_EXCLK, -1, -1, -1 }, 432 .gate = { CGU_REG_CLKGR, 14 }, 433 }, 434 435 [X1000_CLK_UART1] = { 436 "uart1", CGU_CLK_GATE, 437 .parents = { X1000_CLK_EXCLK, -1, -1, -1 }, 438 .gate = { CGU_REG_CLKGR, 15 }, 439 }, 440 441 [X1000_CLK_UART2] = { 442 "uart2", CGU_CLK_GATE, 443 .parents = { X1000_CLK_EXCLK, -1, -1, -1 }, 444 .gate = { CGU_REG_CLKGR, 16 }, 445 }, 446 447 [X1000_CLK_TCU] = { 448 "tcu", CGU_CLK_GATE, 449 .parents = { X1000_CLK_EXCLK, -1, -1, -1 }, 450 .gate = { CGU_REG_CLKGR, 18 }, 451 }, 452 453 [X1000_CLK_SSI] = { 454 "ssi", CGU_CLK_GATE, 455 .parents = { X1000_CLK_SSIMUX, -1, -1, -1 }, 456 .gate = { CGU_REG_CLKGR, 19 }, 457 }, 458 459 [X1000_CLK_OST] = { 460 "ost", CGU_CLK_GATE, 461 .parents = { X1000_CLK_EXCLK, -1, -1, -1 }, 462 .gate = { CGU_REG_CLKGR, 20 }, 463 }, 464 465 [X1000_CLK_PDMA] = { 466 "pdma", CGU_CLK_GATE, 467 .parents = { X1000_CLK_EXCLK, -1, -1, -1 }, 468 .gate = { CGU_REG_CLKGR, 21 }, 469 }, 470}; 471 472static void __init x1000_cgu_init(struct device_node *np) 473{ 474 int retval; 475 476 cgu = ingenic_cgu_new(x1000_cgu_clocks, 477 ARRAY_SIZE(x1000_cgu_clocks), np); 478 if (!cgu) { 479 pr_err("%s: failed to initialise CGU\n", __func__); 480 return; 481 } 482 483 retval = ingenic_cgu_register_clocks(cgu); 484 if (retval) { 485 pr_err("%s: failed to register CGU Clocks\n", __func__); 486 return; 487 } 488 489 ingenic_cgu_register_syscore_ops(cgu); 490} 491/* 492 * CGU has some children devices, this is useful for probing children devices 493 * in the case where the device node is compatible with "simple-mfd". 494 */ 495CLK_OF_DECLARE_DRIVER(x1000_cgu, "ingenic,x1000-cgu", x1000_cgu_init);