1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * JZ4760 SoC CGU driver 4 * Copyright 2018, Paul Cercueil <paul@crapouillou.net> 5 */ 6 7 #include <linux/bitops.h> 8 #include <linux/clk-provider.h> 9 #include <linux/delay.h> 10 #include <linux/io.h> 11 #include <linux/of.h> 12 13 #include <linux/clk.h> 14 15 #include <dt-bindings/clock/ingenic,jz4760-cgu.h> 16 17 #include "cgu.h" 18 #include "pm.h" 19 20 #define MHZ (1000 * 1000) 21 22 /* 23 * CPM registers offset address definition 24 */ 25 #define CGU_REG_CPCCR 0x00 26 #define CGU_REG_LCR 0x04 27 #define CGU_REG_CPPCR0 0x10 28 #define CGU_REG_CLKGR0 0x20 29 #define CGU_REG_OPCR 0x24 30 #define CGU_REG_CLKGR1 0x28 31 #define CGU_REG_CPPCR1 0x30 32 #define CGU_REG_USBPCR 0x3c 33 #define CGU_REG_USBCDR 0x50 34 #define CGU_REG_I2SCDR 0x60 35 #define CGU_REG_LPCDR 0x64 36 #define CGU_REG_MSCCDR 0x68 37 #define CGU_REG_UHCCDR 0x6c 38 #define CGU_REG_SSICDR 0x74 39 #define CGU_REG_CIMCDR 0x7c 40 #define CGU_REG_GPSCDR 0x80 41 #define CGU_REG_PCMCDR 0x84 42 #define CGU_REG_GPUCDR 0x88 43 44 static const s8 pll_od_encoding[8] = { 45 0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3, 46 }; 47 48 static const u8 jz4760_cgu_cpccr_div_table[] = { 49 1, 2, 3, 4, 6, 8, 50 }; 51 52 static const u8 jz4760_cgu_pll_half_div_table[] = { 53 2, 1, 54 }; 55 56 static void 57 jz4760_cgu_calc_m_n_od(const struct ingenic_cgu_pll_info *pll_info, 58 unsigned long rate, unsigned long parent_rate, 59 unsigned int *pm, unsigned int *pn, unsigned int *pod) 60 { 61 unsigned int m, n, od, m_max = (1 << pll_info->m_bits) - 2; 62 63 /* The frequency after the N divider must be between 1 and 50 MHz. */ 64 n = parent_rate / (1 * MHZ); 65 66 /* The N divider must be >= 2. */ 67 n = clamp_val(n, 2, 1 << pll_info->n_bits); 68 69 for (;; n >>= 1) { 70 od = (unsigned int)-1; 71 72 do { 73 m = (rate / MHZ) * (1 << ++od) * n / (parent_rate / MHZ); 74 } while ((m > m_max || m & 1) && (od < 4)); 75 76 if (od < 4 && m >= 4 && m <= m_max) 77 break; 78 } 79 80 *pm = m; 81 *pn = n; 82 *pod = 1 << od; 83 } 84 85 static const struct ingenic_cgu_clk_info jz4760_cgu_clocks[] = { 86 87 /* External clocks */ 88 89 [JZ4760_CLK_EXT] = { "ext", CGU_CLK_EXT }, 90 [JZ4760_CLK_OSC32K] = { "osc32k", CGU_CLK_EXT }, 91 92 /* PLLs */ 93 94 [JZ4760_CLK_PLL0] = { 95 "pll0", CGU_CLK_PLL, 96 .parents = { JZ4760_CLK_EXT }, 97 .pll = { 98 .reg = CGU_REG_CPPCR0, 99 .rate_multiplier = 1, 100 .m_shift = 23, 101 .m_bits = 8, 102 .m_offset = 0, 103 .n_shift = 18, 104 .n_bits = 4, 105 .n_offset = 0, 106 .od_shift = 16, 107 .od_bits = 2, 108 .od_max = 8, 109 .od_encoding = pll_od_encoding, 110 .bypass_reg = CGU_REG_CPPCR0, 111 .bypass_bit = 9, 112 .enable_bit = 8, 113 .stable_bit = 10, 114 .calc_m_n_od = jz4760_cgu_calc_m_n_od, 115 }, 116 }, 117 118 [JZ4760_CLK_PLL1] = { 119 /* TODO: PLL1 can depend on PLL0 */ 120 "pll1", CGU_CLK_PLL, 121 .parents = { JZ4760_CLK_EXT }, 122 .pll = { 123 .reg = CGU_REG_CPPCR1, 124 .rate_multiplier = 1, 125 .m_shift = 23, 126 .m_bits = 8, 127 .m_offset = 0, 128 .n_shift = 18, 129 .n_bits = 4, 130 .n_offset = 0, 131 .od_shift = 16, 132 .od_bits = 2, 133 .od_max = 8, 134 .od_encoding = pll_od_encoding, 135 .bypass_bit = -1, 136 .enable_bit = 7, 137 .stable_bit = 6, 138 .calc_m_n_od = jz4760_cgu_calc_m_n_od, 139 }, 140 }, 141 142 /* Main clocks */ 143 144 [JZ4760_CLK_CCLK] = { 145 "cclk", CGU_CLK_DIV, 146 .parents = { JZ4760_CLK_PLL0, }, 147 .div = { 148 CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, 0, 149 jz4760_cgu_cpccr_div_table, 150 }, 151 }, 152 [JZ4760_CLK_HCLK] = { 153 "hclk", CGU_CLK_DIV, 154 .parents = { JZ4760_CLK_PLL0, }, 155 .div = { 156 CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, 0, 157 jz4760_cgu_cpccr_div_table, 158 }, 159 }, 160 [JZ4760_CLK_SCLK] = { 161 "sclk", CGU_CLK_DIV, 162 .parents = { JZ4760_CLK_PLL0, }, 163 .div = { 164 CGU_REG_CPCCR, 24, 1, 4, 22, -1, -1, 0, 165 jz4760_cgu_cpccr_div_table, 166 }, 167 }, 168 [JZ4760_CLK_H2CLK] = { 169 "h2clk", CGU_CLK_DIV, 170 .parents = { JZ4760_CLK_PLL0, }, 171 .div = { 172 CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1, 0, 173 jz4760_cgu_cpccr_div_table, 174 }, 175 }, 176 [JZ4760_CLK_MCLK] = { 177 "mclk", CGU_CLK_DIV, 178 .parents = { JZ4760_CLK_PLL0, }, 179 .div = { 180 CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, 0, 181 jz4760_cgu_cpccr_div_table, 182 }, 183 }, 184 [JZ4760_CLK_PCLK] = { 185 "pclk", CGU_CLK_DIV, 186 .parents = { JZ4760_CLK_PLL0, }, 187 .div = { 188 CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, 0, 189 jz4760_cgu_cpccr_div_table, 190 }, 191 }, 192 193 /* Divided clocks */ 194 195 [JZ4760_CLK_PLL0_HALF] = { 196 "pll0_half", CGU_CLK_DIV, 197 .parents = { JZ4760_CLK_PLL0 }, 198 .div = { 199 CGU_REG_CPCCR, 21, 1, 1, 22, -1, -1, 0, 200 jz4760_cgu_pll_half_div_table, 201 }, 202 }, 203 204 /* Those divided clocks can connect to PLL0 or PLL1 */ 205 206 [JZ4760_CLK_UHC] = { 207 "uhc", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, 208 .parents = { JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1, }, 209 .mux = { CGU_REG_UHCCDR, 31, 1 }, 210 .div = { CGU_REG_UHCCDR, 0, 1, 4, -1, -1, -1 }, 211 .gate = { CGU_REG_CLKGR0, 24 }, 212 }, 213 [JZ4760_CLK_GPU] = { 214 "gpu", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, 215 .parents = { JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1, }, 216 .mux = { CGU_REG_GPUCDR, 31, 1 }, 217 .div = { CGU_REG_GPUCDR, 0, 1, 3, -1, -1, -1 }, 218 .gate = { CGU_REG_CLKGR1, 9 }, 219 }, 220 [JZ4760_CLK_LPCLK_DIV] = { 221 "lpclk_div", CGU_CLK_DIV | CGU_CLK_MUX, 222 .parents = { JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1, }, 223 .mux = { CGU_REG_LPCDR, 29, 1 }, 224 .div = { CGU_REG_LPCDR, 0, 1, 11, -1, -1, -1 }, 225 }, 226 [JZ4760_CLK_TVE] = { 227 "tve", CGU_CLK_GATE | CGU_CLK_MUX, 228 .parents = { JZ4760_CLK_LPCLK_DIV, JZ4760_CLK_EXT, }, 229 .mux = { CGU_REG_LPCDR, 31, 1 }, 230 .gate = { CGU_REG_CLKGR0, 27 }, 231 }, 232 [JZ4760_CLK_LPCLK] = { 233 "lpclk", CGU_CLK_GATE | CGU_CLK_MUX, 234 .parents = { JZ4760_CLK_LPCLK_DIV, JZ4760_CLK_TVE, }, 235 .mux = { CGU_REG_LPCDR, 30, 1 }, 236 .gate = { CGU_REG_CLKGR0, 28 }, 237 }, 238 [JZ4760_CLK_GPS] = { 239 "gps", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, 240 .parents = { JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1, }, 241 .mux = { CGU_REG_GPSCDR, 31, 1 }, 242 .div = { CGU_REG_GPSCDR, 0, 1, 4, -1, -1, -1 }, 243 .gate = { CGU_REG_CLKGR0, 22 }, 244 }, 245 246 /* Those divided clocks can connect to EXT, PLL0 or PLL1 */ 247 248 [JZ4760_CLK_PCM] = { 249 "pcm", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, 250 .parents = { JZ4760_CLK_EXT, -1, 251 JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1 }, 252 .mux = { CGU_REG_PCMCDR, 30, 2 }, 253 .div = { CGU_REG_PCMCDR, 0, 1, 9, -1, -1, -1, BIT(0) }, 254 .gate = { CGU_REG_CLKGR1, 8 }, 255 }, 256 [JZ4760_CLK_I2S] = { 257 "i2s", CGU_CLK_DIV | CGU_CLK_MUX, 258 .parents = { JZ4760_CLK_EXT, -1, 259 JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1 }, 260 .mux = { CGU_REG_I2SCDR, 30, 2 }, 261 .div = { CGU_REG_I2SCDR, 0, 1, 9, -1, -1, -1, BIT(0) }, 262 }, 263 [JZ4760_CLK_OTG] = { 264 "usb", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, 265 .parents = { JZ4760_CLK_EXT, -1, 266 JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1 }, 267 .mux = { CGU_REG_USBCDR, 30, 2 }, 268 .div = { CGU_REG_USBCDR, 0, 1, 8, -1, -1, -1 }, 269 .gate = { CGU_REG_CLKGR0, 2 }, 270 }, 271 272 /* Those divided clocks can connect to EXT or PLL0 */ 273 [JZ4760_CLK_MMC_MUX] = { 274 "mmc_mux", CGU_CLK_MUX | CGU_CLK_DIV, 275 .parents = { JZ4760_CLK_EXT, JZ4760_CLK_PLL0_HALF, }, 276 .mux = { CGU_REG_MSCCDR, 31, 1 }, 277 .div = { CGU_REG_MSCCDR, 0, 1, 6, -1, -1, -1, BIT(0) }, 278 }, 279 [JZ4760_CLK_SSI_MUX] = { 280 "ssi_mux", CGU_CLK_DIV | CGU_CLK_MUX, 281 .parents = { JZ4760_CLK_EXT, JZ4760_CLK_PLL0_HALF, }, 282 .mux = { CGU_REG_SSICDR, 31, 1 }, 283 .div = { CGU_REG_SSICDR, 0, 1, 6, -1, -1, -1, BIT(0) }, 284 }, 285 286 /* These divided clock can connect to PLL0 only */ 287 [JZ4760_CLK_CIM] = { 288 "cim", CGU_CLK_DIV | CGU_CLK_GATE, 289 .parents = { JZ4760_CLK_PLL0_HALF }, 290 .div = { CGU_REG_CIMCDR, 0, 1, 8, -1, -1, -1 }, 291 .gate = { CGU_REG_CLKGR0, 26 }, 292 }, 293 294 /* Gate-only clocks */ 295 296 [JZ4760_CLK_SSI0] = { 297 "ssi0", CGU_CLK_GATE, 298 .parents = { JZ4760_CLK_SSI_MUX, }, 299 .gate = { CGU_REG_CLKGR0, 4 }, 300 }, 301 [JZ4760_CLK_SSI1] = { 302 "ssi1", CGU_CLK_GATE, 303 .parents = { JZ4760_CLK_SSI_MUX, }, 304 .gate = { CGU_REG_CLKGR0, 19 }, 305 }, 306 [JZ4760_CLK_SSI2] = { 307 "ssi2", CGU_CLK_GATE, 308 .parents = { JZ4760_CLK_SSI_MUX, }, 309 .gate = { CGU_REG_CLKGR0, 20 }, 310 }, 311 [JZ4760_CLK_DMA] = { 312 "dma", CGU_CLK_GATE, 313 .parents = { JZ4760_CLK_H2CLK, }, 314 .gate = { CGU_REG_CLKGR0, 21 }, 315 }, 316 [JZ4760_CLK_MDMA] = { 317 "mdma", CGU_CLK_GATE, 318 .parents = { JZ4760_CLK_HCLK, }, 319 .gate = { CGU_REG_CLKGR0, 25 }, 320 }, 321 [JZ4760_CLK_BDMA] = { 322 "bdma", CGU_CLK_GATE, 323 .parents = { JZ4760_CLK_HCLK, }, 324 .gate = { CGU_REG_CLKGR1, 0 }, 325 }, 326 [JZ4760_CLK_I2C0] = { 327 "i2c0", CGU_CLK_GATE, 328 .parents = { JZ4760_CLK_EXT, }, 329 .gate = { CGU_REG_CLKGR0, 5 }, 330 }, 331 [JZ4760_CLK_I2C1] = { 332 "i2c1", CGU_CLK_GATE, 333 .parents = { JZ4760_CLK_EXT, }, 334 .gate = { CGU_REG_CLKGR0, 6 }, 335 }, 336 [JZ4760_CLK_UART0] = { 337 "uart0", CGU_CLK_GATE, 338 .parents = { JZ4760_CLK_EXT, }, 339 .gate = { CGU_REG_CLKGR0, 15 }, 340 }, 341 [JZ4760_CLK_UART1] = { 342 "uart1", CGU_CLK_GATE, 343 .parents = { JZ4760_CLK_EXT, }, 344 .gate = { CGU_REG_CLKGR0, 16 }, 345 }, 346 [JZ4760_CLK_UART2] = { 347 "uart2", CGU_CLK_GATE, 348 .parents = { JZ4760_CLK_EXT, }, 349 .gate = { CGU_REG_CLKGR0, 17 }, 350 }, 351 [JZ4760_CLK_UART3] = { 352 "uart3", CGU_CLK_GATE, 353 .parents = { JZ4760_CLK_EXT, }, 354 .gate = { CGU_REG_CLKGR0, 18 }, 355 }, 356 [JZ4760_CLK_IPU] = { 357 "ipu", CGU_CLK_GATE, 358 .parents = { JZ4760_CLK_HCLK, }, 359 .gate = { CGU_REG_CLKGR0, 29 }, 360 }, 361 [JZ4760_CLK_ADC] = { 362 "adc", CGU_CLK_GATE, 363 .parents = { JZ4760_CLK_EXT, }, 364 .gate = { CGU_REG_CLKGR0, 14 }, 365 }, 366 [JZ4760_CLK_AIC] = { 367 "aic", CGU_CLK_GATE, 368 .parents = { JZ4760_CLK_EXT, }, 369 .gate = { CGU_REG_CLKGR0, 8 }, 370 }, 371 [JZ4760_CLK_VPU] = { 372 "vpu", CGU_CLK_GATE, 373 .parents = { JZ4760_CLK_HCLK, }, 374 .gate = { CGU_REG_LCR, 30, false, 150 }, 375 }, 376 [JZ4760_CLK_MMC0] = { 377 "mmc0", CGU_CLK_GATE, 378 .parents = { JZ4760_CLK_MMC_MUX, }, 379 .gate = { CGU_REG_CLKGR0, 3 }, 380 }, 381 [JZ4760_CLK_MMC1] = { 382 "mmc1", CGU_CLK_GATE, 383 .parents = { JZ4760_CLK_MMC_MUX, }, 384 .gate = { CGU_REG_CLKGR0, 11 }, 385 }, 386 [JZ4760_CLK_MMC2] = { 387 "mmc2", CGU_CLK_GATE, 388 .parents = { JZ4760_CLK_MMC_MUX, }, 389 .gate = { CGU_REG_CLKGR0, 12 }, 390 }, 391 [JZ4760_CLK_UHC_PHY] = { 392 "uhc_phy", CGU_CLK_GATE, 393 .parents = { JZ4760_CLK_UHC, }, 394 .gate = { CGU_REG_OPCR, 5 }, 395 }, 396 [JZ4760_CLK_OTG_PHY] = { 397 "usb_phy", CGU_CLK_GATE, 398 .parents = { JZ4760_CLK_OTG }, 399 .gate = { CGU_REG_OPCR, 7, true, 50 }, 400 }, 401 402 /* Custom clocks */ 403 [JZ4760_CLK_EXT512] = { 404 "ext/512", CGU_CLK_FIXDIV, 405 .parents = { JZ4760_CLK_EXT }, 406 .fixdiv = { 512 }, 407 }, 408 [JZ4760_CLK_RTC] = { 409 "rtc", CGU_CLK_MUX, 410 .parents = { JZ4760_CLK_EXT512, JZ4760_CLK_OSC32K, }, 411 .mux = { CGU_REG_OPCR, 2, 1}, 412 }, 413 }; 414 415 static void __init jz4760_cgu_init(struct device_node *np) 416 { 417 struct ingenic_cgu *cgu; 418 int retval; 419 420 cgu = ingenic_cgu_new(jz4760_cgu_clocks, 421 ARRAY_SIZE(jz4760_cgu_clocks), np); 422 if (!cgu) { 423 pr_err("%s: failed to initialise CGU\n", __func__); 424 return; 425 } 426 427 retval = ingenic_cgu_register_clocks(cgu); 428 if (retval) 429 pr_err("%s: failed to register CGU Clocks\n", __func__); 430 431 ingenic_cgu_register_syscore_ops(cgu); 432 } 433 434 /* We only probe via devicetree, no need for a platform driver */ 435 CLK_OF_DECLARE_DRIVER(jz4760_cgu, "ingenic,jz4760-cgu", jz4760_cgu_init); 436 437 /* JZ4760B has some small differences, but we don't implement them. */ 438 CLK_OF_DECLARE_DRIVER(jz4760b_cgu, "ingenic,jz4760b-cgu", jz4760_cgu_init); 439