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 /* Gate-only clocks */ 282 283 [X1000_CLK_EMC] = { 284 "emc", CGU_CLK_GATE, 285 .parents = { X1000_CLK_AHB2, -1, -1, -1 }, 286 .gate = { CGU_REG_CLKGR, 0 }, 287 }, 288 289 [X1000_CLK_EFUSE] = { 290 "efuse", CGU_CLK_GATE, 291 .parents = { X1000_CLK_AHB2, -1, -1, -1 }, 292 .gate = { CGU_REG_CLKGR, 1 }, 293 }, 294 295 [X1000_CLK_SFC] = { 296 "sfc", CGU_CLK_GATE, 297 .parents = { X1000_CLK_SSIPLL, -1, -1, -1 }, 298 .gate = { CGU_REG_CLKGR, 2 }, 299 }, 300 301 [X1000_CLK_I2C0] = { 302 "i2c0", CGU_CLK_GATE, 303 .parents = { X1000_CLK_PCLK, -1, -1, -1 }, 304 .gate = { CGU_REG_CLKGR, 7 }, 305 }, 306 307 [X1000_CLK_I2C1] = { 308 "i2c1", CGU_CLK_GATE, 309 .parents = { X1000_CLK_PCLK, -1, -1, -1 }, 310 .gate = { CGU_REG_CLKGR, 8 }, 311 }, 312 313 [X1000_CLK_I2C2] = { 314 "i2c2", CGU_CLK_GATE, 315 .parents = { X1000_CLK_PCLK, -1, -1, -1 }, 316 .gate = { CGU_REG_CLKGR, 9 }, 317 }, 318 319 [X1000_CLK_UART0] = { 320 "uart0", CGU_CLK_GATE, 321 .parents = { X1000_CLK_EXCLK, -1, -1, -1 }, 322 .gate = { CGU_REG_CLKGR, 14 }, 323 }, 324 325 [X1000_CLK_UART1] = { 326 "uart1", CGU_CLK_GATE, 327 .parents = { X1000_CLK_EXCLK, -1, -1, -1 }, 328 .gate = { CGU_REG_CLKGR, 15 }, 329 }, 330 331 [X1000_CLK_UART2] = { 332 "uart2", CGU_CLK_GATE, 333 .parents = { X1000_CLK_EXCLK, -1, -1, -1 }, 334 .gate = { CGU_REG_CLKGR, 16 }, 335 }, 336 337 [X1000_CLK_TCU] = { 338 "tcu", CGU_CLK_GATE, 339 .parents = { X1000_CLK_EXCLK, -1, -1, -1 }, 340 .gate = { CGU_REG_CLKGR, 18 }, 341 }, 342 343 [X1000_CLK_SSI] = { 344 "ssi", CGU_CLK_GATE, 345 .parents = { X1000_CLK_SSIMUX, -1, -1, -1 }, 346 .gate = { CGU_REG_CLKGR, 19 }, 347 }, 348 349 [X1000_CLK_OST] = { 350 "ost", CGU_CLK_GATE, 351 .parents = { X1000_CLK_EXCLK, -1, -1, -1 }, 352 .gate = { CGU_REG_CLKGR, 20 }, 353 }, 354 355 [X1000_CLK_PDMA] = { 356 "pdma", CGU_CLK_GATE, 357 .parents = { X1000_CLK_EXCLK, -1, -1, -1 }, 358 .gate = { CGU_REG_CLKGR, 21 }, 359 }, 360 }; 361 362 static void __init x1000_cgu_init(struct device_node *np) 363 { 364 int retval; 365 366 cgu = ingenic_cgu_new(x1000_cgu_clocks, 367 ARRAY_SIZE(x1000_cgu_clocks), np); 368 if (!cgu) { 369 pr_err("%s: failed to initialise CGU\n", __func__); 370 return; 371 } 372 373 retval = ingenic_cgu_register_clocks(cgu); 374 if (retval) { 375 pr_err("%s: failed to register CGU Clocks\n", __func__); 376 return; 377 } 378 379 ingenic_cgu_register_syscore_ops(cgu); 380 } 381 /* 382 * CGU has some children devices, this is useful for probing children devices 383 * in the case where the device node is compatible with "simple-mfd". 384 */ 385 CLK_OF_DECLARE_DRIVER(x1000_cgu, "ingenic,x1000-cgu", x1000_cgu_init); 386