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/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 static struct ingenic_cgu *cgu; 52 53 static int x1000_usb_phy_enable(struct clk_hw *hw) 54 { 55 void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR; 56 void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR; 57 58 writel(readl(reg_opcr) | OPCR_SPENDN0, reg_opcr); 59 writel(readl(reg_usbpcr) & ~USBPCR_OTG_DISABLE & ~USBPCR_SIDDQ, reg_usbpcr); 60 return 0; 61 } 62 63 static void x1000_usb_phy_disable(struct clk_hw *hw) 64 { 65 void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR; 66 void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR; 67 68 writel(readl(reg_opcr) & ~OPCR_SPENDN0, reg_opcr); 69 writel(readl(reg_usbpcr) | USBPCR_OTG_DISABLE | USBPCR_SIDDQ, reg_usbpcr); 70 } 71 72 static int x1000_usb_phy_is_enabled(struct clk_hw *hw) 73 { 74 void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR; 75 void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR; 76 77 return (readl(reg_opcr) & OPCR_SPENDN0) && 78 !(readl(reg_usbpcr) & USBPCR_SIDDQ) && 79 !(readl(reg_usbpcr) & USBPCR_OTG_DISABLE); 80 } 81 82 static const struct clk_ops x1000_otg_phy_ops = { 83 .enable = x1000_usb_phy_enable, 84 .disable = x1000_usb_phy_disable, 85 .is_enabled = x1000_usb_phy_is_enabled, 86 }; 87 88 static const s8 pll_od_encoding[8] = { 89 0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3, 90 }; 91 92 static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = { 93 94 /* External clocks */ 95 96 [X1000_CLK_EXCLK] = { "ext", CGU_CLK_EXT }, 97 [X1000_CLK_RTCLK] = { "rtc", CGU_CLK_EXT }, 98 99 /* PLLs */ 100 101 [X1000_CLK_APLL] = { 102 "apll", CGU_CLK_PLL, 103 .parents = { X1000_CLK_EXCLK, -1, -1, -1 }, 104 .pll = { 105 .reg = CGU_REG_APLL, 106 .rate_multiplier = 1, 107 .m_shift = 24, 108 .m_bits = 7, 109 .m_offset = 1, 110 .n_shift = 18, 111 .n_bits = 5, 112 .n_offset = 1, 113 .od_shift = 16, 114 .od_bits = 2, 115 .od_max = 8, 116 .od_encoding = pll_od_encoding, 117 .bypass_reg = CGU_REG_APLL, 118 .bypass_bit = 9, 119 .enable_bit = 8, 120 .stable_bit = 10, 121 }, 122 }, 123 124 [X1000_CLK_MPLL] = { 125 "mpll", CGU_CLK_PLL, 126 .parents = { X1000_CLK_EXCLK, -1, -1, -1 }, 127 .pll = { 128 .reg = CGU_REG_MPLL, 129 .rate_multiplier = 1, 130 .m_shift = 24, 131 .m_bits = 7, 132 .m_offset = 1, 133 .n_shift = 18, 134 .n_bits = 5, 135 .n_offset = 1, 136 .od_shift = 16, 137 .od_bits = 2, 138 .od_max = 8, 139 .od_encoding = pll_od_encoding, 140 .bypass_reg = CGU_REG_MPLL, 141 .bypass_bit = 6, 142 .enable_bit = 7, 143 .stable_bit = 0, 144 }, 145 }, 146 147 148 /* Custom (SoC-specific) OTG PHY */ 149 150 [X1000_CLK_OTGPHY] = { 151 "otg_phy", CGU_CLK_CUSTOM, 152 .parents = { -1, -1, X1000_CLK_EXCLK, -1 }, 153 .custom = { &x1000_otg_phy_ops }, 154 }, 155 156 /* Muxes & dividers */ 157 158 [X1000_CLK_SCLKA] = { 159 "sclk_a", CGU_CLK_MUX, 160 .parents = { -1, X1000_CLK_EXCLK, X1000_CLK_APLL, -1 }, 161 .mux = { CGU_REG_CPCCR, 30, 2 }, 162 }, 163 164 [X1000_CLK_CPUMUX] = { 165 "cpu_mux", CGU_CLK_MUX, 166 .parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 }, 167 .mux = { CGU_REG_CPCCR, 28, 2 }, 168 }, 169 170 [X1000_CLK_CPU] = { 171 "cpu", CGU_CLK_DIV | CGU_CLK_GATE, 172 .parents = { X1000_CLK_CPUMUX, -1, -1, -1 }, 173 .div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1 }, 174 .gate = { CGU_REG_CLKGR, 30 }, 175 }, 176 177 [X1000_CLK_L2CACHE] = { 178 "l2cache", CGU_CLK_DIV, 179 .parents = { X1000_CLK_CPUMUX, -1, -1, -1 }, 180 .div = { CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1 }, 181 }, 182 183 [X1000_CLK_AHB0] = { 184 "ahb0", CGU_CLK_MUX | CGU_CLK_DIV, 185 .parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 }, 186 .mux = { CGU_REG_CPCCR, 26, 2 }, 187 .div = { CGU_REG_CPCCR, 8, 1, 4, 21, -1, -1 }, 188 }, 189 190 [X1000_CLK_AHB2PMUX] = { 191 "ahb2_apb_mux", CGU_CLK_MUX, 192 .parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 }, 193 .mux = { CGU_REG_CPCCR, 24, 2 }, 194 }, 195 196 [X1000_CLK_AHB2] = { 197 "ahb2", CGU_CLK_DIV, 198 .parents = { X1000_CLK_AHB2PMUX, -1, -1, -1 }, 199 .div = { CGU_REG_CPCCR, 12, 1, 4, 20, -1, -1 }, 200 }, 201 202 [X1000_CLK_PCLK] = { 203 "pclk", CGU_CLK_DIV | CGU_CLK_GATE, 204 .parents = { X1000_CLK_AHB2PMUX, -1, -1, -1 }, 205 .div = { CGU_REG_CPCCR, 16, 1, 4, 20, -1, -1 }, 206 .gate = { CGU_REG_CLKGR, 28 }, 207 }, 208 209 [X1000_CLK_DDR] = { 210 "ddr", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE, 211 .parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 }, 212 .mux = { CGU_REG_DDRCDR, 30, 2 }, 213 .div = { CGU_REG_DDRCDR, 0, 1, 4, 29, 28, 27 }, 214 .gate = { CGU_REG_CLKGR, 31 }, 215 }, 216 217 [X1000_CLK_MAC] = { 218 "mac", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE, 219 .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL }, 220 .mux = { CGU_REG_MACCDR, 31, 1 }, 221 .div = { CGU_REG_MACCDR, 0, 1, 8, 29, 28, 27 }, 222 .gate = { CGU_REG_CLKGR, 25 }, 223 }, 224 225 [X1000_CLK_LCD] = { 226 "lcd", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE, 227 .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL }, 228 .mux = { CGU_REG_LPCDR, 31, 1 }, 229 .div = { CGU_REG_LPCDR, 0, 1, 8, 28, 27, 26 }, 230 .gate = { CGU_REG_CLKGR, 23 }, 231 }, 232 233 [X1000_CLK_MSCMUX] = { 234 "msc_mux", CGU_CLK_MUX, 235 .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL}, 236 .mux = { CGU_REG_MSC0CDR, 31, 1 }, 237 }, 238 239 [X1000_CLK_MSC0] = { 240 "msc0", CGU_CLK_DIV | CGU_CLK_GATE, 241 .parents = { X1000_CLK_MSCMUX, -1, -1, -1 }, 242 .div = { CGU_REG_MSC0CDR, 0, 2, 8, 29, 28, 27 }, 243 .gate = { CGU_REG_CLKGR, 4 }, 244 }, 245 246 [X1000_CLK_MSC1] = { 247 "msc1", CGU_CLK_DIV | CGU_CLK_GATE, 248 .parents = { X1000_CLK_MSCMUX, -1, -1, -1 }, 249 .div = { CGU_REG_MSC1CDR, 0, 2, 8, 29, 28, 27 }, 250 .gate = { CGU_REG_CLKGR, 5 }, 251 }, 252 253 [X1000_CLK_OTG] = { 254 "otg", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, 255 .parents = { X1000_CLK_EXCLK, -1, 256 X1000_CLK_APLL, X1000_CLK_MPLL }, 257 .mux = { CGU_REG_USBCDR, 30, 2 }, 258 .div = { CGU_REG_USBCDR, 0, 1, 8, 29, 28, 27 }, 259 .gate = { CGU_REG_CLKGR, 3 }, 260 }, 261 262 [X1000_CLK_SSIPLL] = { 263 "ssi_pll", CGU_CLK_MUX | CGU_CLK_DIV, 264 .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL, -1, -1 }, 265 .mux = { CGU_REG_SSICDR, 31, 1 }, 266 .div = { CGU_REG_SSICDR, 0, 1, 8, 29, 28, 27 }, 267 }, 268 269 [X1000_CLK_SSIPLL_DIV2] = { 270 "ssi_pll_div2", CGU_CLK_FIXDIV, 271 .parents = { X1000_CLK_SSIPLL }, 272 .fixdiv = { 2 }, 273 }, 274 275 [X1000_CLK_SSIMUX] = { 276 "ssi_mux", CGU_CLK_MUX, 277 .parents = { X1000_CLK_EXCLK, X1000_CLK_SSIPLL_DIV2, -1, -1 }, 278 .mux = { CGU_REG_SSICDR, 30, 1 }, 279 }, 280 281 [X1000_CLK_EXCLK_DIV512] = { 282 "exclk_div512", CGU_CLK_FIXDIV, 283 .parents = { X1000_CLK_EXCLK }, 284 .fixdiv = { 512 }, 285 }, 286 287 [X1000_CLK_RTC] = { 288 "rtc_ercs", CGU_CLK_MUX | CGU_CLK_GATE, 289 .parents = { X1000_CLK_EXCLK_DIV512, X1000_CLK_RTCLK }, 290 .mux = { CGU_REG_OPCR, 2, 1}, 291 .gate = { CGU_REG_CLKGR, 27 }, 292 }, 293 294 /* Gate-only clocks */ 295 296 [X1000_CLK_EMC] = { 297 "emc", CGU_CLK_GATE, 298 .parents = { X1000_CLK_AHB2, -1, -1, -1 }, 299 .gate = { CGU_REG_CLKGR, 0 }, 300 }, 301 302 [X1000_CLK_EFUSE] = { 303 "efuse", CGU_CLK_GATE, 304 .parents = { X1000_CLK_AHB2, -1, -1, -1 }, 305 .gate = { CGU_REG_CLKGR, 1 }, 306 }, 307 308 [X1000_CLK_SFC] = { 309 "sfc", CGU_CLK_GATE, 310 .parents = { X1000_CLK_SSIPLL, -1, -1, -1 }, 311 .gate = { CGU_REG_CLKGR, 2 }, 312 }, 313 314 [X1000_CLK_I2C0] = { 315 "i2c0", CGU_CLK_GATE, 316 .parents = { X1000_CLK_PCLK, -1, -1, -1 }, 317 .gate = { CGU_REG_CLKGR, 7 }, 318 }, 319 320 [X1000_CLK_I2C1] = { 321 "i2c1", CGU_CLK_GATE, 322 .parents = { X1000_CLK_PCLK, -1, -1, -1 }, 323 .gate = { CGU_REG_CLKGR, 8 }, 324 }, 325 326 [X1000_CLK_I2C2] = { 327 "i2c2", CGU_CLK_GATE, 328 .parents = { X1000_CLK_PCLK, -1, -1, -1 }, 329 .gate = { CGU_REG_CLKGR, 9 }, 330 }, 331 332 [X1000_CLK_UART0] = { 333 "uart0", CGU_CLK_GATE, 334 .parents = { X1000_CLK_EXCLK, -1, -1, -1 }, 335 .gate = { CGU_REG_CLKGR, 14 }, 336 }, 337 338 [X1000_CLK_UART1] = { 339 "uart1", CGU_CLK_GATE, 340 .parents = { X1000_CLK_EXCLK, -1, -1, -1 }, 341 .gate = { CGU_REG_CLKGR, 15 }, 342 }, 343 344 [X1000_CLK_UART2] = { 345 "uart2", CGU_CLK_GATE, 346 .parents = { X1000_CLK_EXCLK, -1, -1, -1 }, 347 .gate = { CGU_REG_CLKGR, 16 }, 348 }, 349 350 [X1000_CLK_TCU] = { 351 "tcu", CGU_CLK_GATE, 352 .parents = { X1000_CLK_EXCLK, -1, -1, -1 }, 353 .gate = { CGU_REG_CLKGR, 18 }, 354 }, 355 356 [X1000_CLK_SSI] = { 357 "ssi", CGU_CLK_GATE, 358 .parents = { X1000_CLK_SSIMUX, -1, -1, -1 }, 359 .gate = { CGU_REG_CLKGR, 19 }, 360 }, 361 362 [X1000_CLK_OST] = { 363 "ost", CGU_CLK_GATE, 364 .parents = { X1000_CLK_EXCLK, -1, -1, -1 }, 365 .gate = { CGU_REG_CLKGR, 20 }, 366 }, 367 368 [X1000_CLK_PDMA] = { 369 "pdma", CGU_CLK_GATE, 370 .parents = { X1000_CLK_EXCLK, -1, -1, -1 }, 371 .gate = { CGU_REG_CLKGR, 21 }, 372 }, 373 }; 374 375 static void __init x1000_cgu_init(struct device_node *np) 376 { 377 int retval; 378 379 cgu = ingenic_cgu_new(x1000_cgu_clocks, 380 ARRAY_SIZE(x1000_cgu_clocks), np); 381 if (!cgu) { 382 pr_err("%s: failed to initialise CGU\n", __func__); 383 return; 384 } 385 386 retval = ingenic_cgu_register_clocks(cgu); 387 if (retval) { 388 pr_err("%s: failed to register CGU Clocks\n", __func__); 389 return; 390 } 391 392 ingenic_cgu_register_syscore_ops(cgu); 393 } 394 /* 395 * CGU has some children devices, this is useful for probing children devices 396 * in the case where the device node is compatible with "simple-mfd". 397 */ 398 CLK_OF_DECLARE_DRIVER(x1000_cgu, "ingenic,x1000-cgu", x1000_cgu_init); 399