1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Ingenic JZ4755 SoC CGU driver 4 * Heavily based on JZ4725b CGU driver 5 * 6 * Copyright (C) 2022 Siarhei Volkau 7 * Author: Siarhei Volkau <lis8215@gmail.com> 8 */ 9 10 #include <linux/clk-provider.h> 11 #include <linux/delay.h> 12 #include <linux/of.h> 13 14 #include <dt-bindings/clock/ingenic,jz4755-cgu.h> 15 16 #include "cgu.h" 17 #include "pm.h" 18 19 /* CGU register offsets */ 20 #define CGU_REG_CPCCR 0x00 21 #define CGU_REG_CPPCR 0x10 22 #define CGU_REG_CLKGR 0x20 23 #define CGU_REG_OPCR 0x24 24 #define CGU_REG_I2SCDR 0x60 25 #define CGU_REG_LPCDR 0x64 26 #define CGU_REG_MSCCDR 0x68 27 #define CGU_REG_SSICDR 0x74 28 #define CGU_REG_CIMCDR 0x7C 29 30 static struct ingenic_cgu *cgu; 31 32 static const s8 pll_od_encoding[4] = { 33 0x0, 0x1, -1, 0x3, 34 }; 35 36 static const u8 jz4755_cgu_cpccr_div_table[] = { 37 1, 2, 3, 4, 6, 8, 38 }; 39 40 static const u8 jz4755_cgu_pll_half_div_table[] = { 41 2, 1, 42 }; 43 44 static const struct ingenic_cgu_clk_info jz4755_cgu_clocks[] = { 45 46 /* External clocks */ 47 48 [JZ4755_CLK_EXT] = { "ext", CGU_CLK_EXT }, 49 [JZ4755_CLK_OSC32K] = { "osc32k", CGU_CLK_EXT }, 50 51 [JZ4755_CLK_PLL] = { 52 "pll", CGU_CLK_PLL, 53 .parents = { JZ4755_CLK_EXT, }, 54 .pll = { 55 .reg = CGU_REG_CPPCR, 56 .rate_multiplier = 1, 57 .m_shift = 23, 58 .m_bits = 9, 59 .m_offset = 2, 60 .n_shift = 18, 61 .n_bits = 5, 62 .n_offset = 2, 63 .od_shift = 16, 64 .od_bits = 2, 65 .od_max = 4, 66 .od_encoding = pll_od_encoding, 67 .stable_bit = 10, 68 .bypass_reg = CGU_REG_CPPCR, 69 .bypass_bit = 9, 70 .enable_bit = 8, 71 }, 72 }, 73 74 /* Muxes & dividers */ 75 76 [JZ4755_CLK_PLL_HALF] = { 77 "pll half", CGU_CLK_DIV, 78 .parents = { JZ4755_CLK_PLL, }, 79 .div = { 80 CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1, 0, 81 jz4755_cgu_pll_half_div_table, 82 }, 83 }, 84 85 [JZ4755_CLK_EXT_HALF] = { 86 "ext half", CGU_CLK_DIV, 87 .parents = { JZ4755_CLK_EXT, }, 88 .div = { 89 CGU_REG_CPCCR, 30, 1, 1, -1, -1, -1, 0, 90 NULL, 91 }, 92 }, 93 94 [JZ4755_CLK_CCLK] = { 95 "cclk", CGU_CLK_DIV, 96 .parents = { JZ4755_CLK_PLL, }, 97 .div = { 98 CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, 0, 99 jz4755_cgu_cpccr_div_table, 100 }, 101 }, 102 103 [JZ4755_CLK_H0CLK] = { 104 "hclk", CGU_CLK_DIV, 105 .parents = { JZ4755_CLK_PLL, }, 106 .div = { 107 CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, 0, 108 jz4755_cgu_cpccr_div_table, 109 }, 110 }, 111 112 [JZ4755_CLK_PCLK] = { 113 "pclk", CGU_CLK_DIV, 114 .parents = { JZ4755_CLK_PLL, }, 115 .div = { 116 CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, 0, 117 jz4755_cgu_cpccr_div_table, 118 }, 119 }, 120 121 [JZ4755_CLK_MCLK] = { 122 "mclk", CGU_CLK_DIV, 123 .parents = { JZ4755_CLK_PLL, }, 124 .div = { 125 CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, 0, 126 jz4755_cgu_cpccr_div_table, 127 }, 128 }, 129 130 [JZ4755_CLK_H1CLK] = { 131 "h1clk", CGU_CLK_DIV, 132 .parents = { JZ4755_CLK_PLL, }, 133 .div = { 134 CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1, 0, 135 jz4755_cgu_cpccr_div_table, 136 }, 137 }, 138 139 [JZ4755_CLK_UDC] = { 140 "udc", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE, 141 .parents = { JZ4755_CLK_EXT_HALF, JZ4755_CLK_PLL_HALF, }, 142 .mux = { CGU_REG_CPCCR, 29, 1 }, 143 .div = { CGU_REG_CPCCR, 23, 1, 6, -1, -1, -1 }, 144 .gate = { CGU_REG_CLKGR, 10 }, 145 }, 146 147 [JZ4755_CLK_LCD] = { 148 "lcd", CGU_CLK_DIV | CGU_CLK_GATE, 149 .parents = { JZ4755_CLK_PLL_HALF, }, 150 .div = { CGU_REG_LPCDR, 0, 1, 11, -1, -1, -1 }, 151 .gate = { CGU_REG_CLKGR, 9 }, 152 }, 153 154 [JZ4755_CLK_MMC] = { 155 "mmc", CGU_CLK_DIV, 156 .parents = { JZ4755_CLK_PLL_HALF, }, 157 .div = { CGU_REG_MSCCDR, 0, 1, 5, -1, -1, -1 }, 158 }, 159 160 [JZ4755_CLK_I2S] = { 161 "i2s", CGU_CLK_MUX | CGU_CLK_DIV, 162 .parents = { JZ4755_CLK_EXT_HALF, JZ4755_CLK_PLL_HALF, }, 163 .mux = { CGU_REG_CPCCR, 31, 1 }, 164 .div = { CGU_REG_I2SCDR, 0, 1, 9, -1, -1, -1 }, 165 }, 166 167 [JZ4755_CLK_SPI] = { 168 "spi", CGU_CLK_DIV | CGU_CLK_GATE, 169 .parents = { JZ4755_CLK_PLL_HALF, }, 170 .div = { CGU_REG_SSICDR, 0, 1, 4, -1, -1, -1 }, 171 .gate = { CGU_REG_CLKGR, 4 }, 172 }, 173 174 [JZ4755_CLK_TVE] = { 175 "tve", CGU_CLK_MUX | CGU_CLK_GATE, 176 .parents = { JZ4755_CLK_LCD, JZ4755_CLK_EXT, }, 177 .mux = { CGU_REG_LPCDR, 31, 1 }, 178 .gate = { CGU_REG_CLKGR, 18 }, 179 }, 180 181 [JZ4755_CLK_RTC] = { 182 "rtc", CGU_CLK_MUX | CGU_CLK_GATE, 183 .parents = { JZ4755_CLK_EXT512, JZ4755_CLK_OSC32K, }, 184 .mux = { CGU_REG_OPCR, 2, 1}, 185 .gate = { CGU_REG_CLKGR, 2 }, 186 }, 187 188 [JZ4755_CLK_CIM] = { 189 "cim", CGU_CLK_DIV | CGU_CLK_GATE, 190 .parents = { JZ4755_CLK_PLL_HALF, }, 191 .div = { CGU_REG_CIMCDR, 0, 1, 8, -1, -1, -1 }, 192 .gate = { CGU_REG_CLKGR, 8 }, 193 }, 194 195 /* Gate-only clocks */ 196 197 [JZ4755_CLK_UART0] = { 198 "uart0", CGU_CLK_GATE, 199 .parents = { JZ4755_CLK_EXT_HALF, }, 200 .gate = { CGU_REG_CLKGR, 0 }, 201 }, 202 203 [JZ4755_CLK_UART1] = { 204 "uart1", CGU_CLK_GATE, 205 .parents = { JZ4755_CLK_EXT_HALF, }, 206 .gate = { CGU_REG_CLKGR, 14 }, 207 }, 208 209 [JZ4755_CLK_UART2] = { 210 "uart2", CGU_CLK_GATE, 211 .parents = { JZ4755_CLK_EXT_HALF, }, 212 .gate = { CGU_REG_CLKGR, 15 }, 213 }, 214 215 [JZ4755_CLK_ADC] = { 216 "adc", CGU_CLK_GATE, 217 .parents = { JZ4755_CLK_EXT_HALF, }, 218 .gate = { CGU_REG_CLKGR, 7 }, 219 }, 220 221 [JZ4755_CLK_AIC] = { 222 "aic", CGU_CLK_GATE, 223 .parents = { JZ4755_CLK_EXT_HALF, }, 224 .gate = { CGU_REG_CLKGR, 5 }, 225 }, 226 227 [JZ4755_CLK_I2C] = { 228 "i2c", CGU_CLK_GATE, 229 .parents = { JZ4755_CLK_EXT_HALF, }, 230 .gate = { CGU_REG_CLKGR, 3 }, 231 }, 232 233 [JZ4755_CLK_BCH] = { 234 "bch", CGU_CLK_GATE, 235 .parents = { JZ4755_CLK_H1CLK, }, 236 .gate = { CGU_REG_CLKGR, 11 }, 237 }, 238 239 [JZ4755_CLK_TCU] = { 240 "tcu", CGU_CLK_GATE, 241 .parents = { JZ4755_CLK_EXT, }, 242 .gate = { CGU_REG_CLKGR, 1 }, 243 }, 244 245 [JZ4755_CLK_DMA] = { 246 "dma", CGU_CLK_GATE, 247 .parents = { JZ4755_CLK_PCLK, }, 248 .gate = { CGU_REG_CLKGR, 12 }, 249 }, 250 251 [JZ4755_CLK_MMC0] = { 252 "mmc0", CGU_CLK_GATE, 253 .parents = { JZ4755_CLK_MMC, }, 254 .gate = { CGU_REG_CLKGR, 6 }, 255 }, 256 257 [JZ4755_CLK_MMC1] = { 258 "mmc1", CGU_CLK_GATE, 259 .parents = { JZ4755_CLK_MMC, }, 260 .gate = { CGU_REG_CLKGR, 16 }, 261 }, 262 263 [JZ4755_CLK_AUX_CPU] = { 264 "aux_cpu", CGU_CLK_GATE, 265 .parents = { JZ4755_CLK_H1CLK, }, 266 .gate = { CGU_REG_CLKGR, 24 }, 267 }, 268 269 [JZ4755_CLK_AHB1] = { 270 "ahb1", CGU_CLK_GATE, 271 .parents = { JZ4755_CLK_H1CLK, }, 272 .gate = { CGU_REG_CLKGR, 23 }, 273 }, 274 275 [JZ4755_CLK_IDCT] = { 276 "idct", CGU_CLK_GATE, 277 .parents = { JZ4755_CLK_H1CLK, }, 278 .gate = { CGU_REG_CLKGR, 22 }, 279 }, 280 281 [JZ4755_CLK_DB] = { 282 "db", CGU_CLK_GATE, 283 .parents = { JZ4755_CLK_H1CLK, }, 284 .gate = { CGU_REG_CLKGR, 21 }, 285 }, 286 287 [JZ4755_CLK_ME] = { 288 "me", CGU_CLK_GATE, 289 .parents = { JZ4755_CLK_H1CLK, }, 290 .gate = { CGU_REG_CLKGR, 20 }, 291 }, 292 293 [JZ4755_CLK_MC] = { 294 "mc", CGU_CLK_GATE, 295 .parents = { JZ4755_CLK_H1CLK, }, 296 .gate = { CGU_REG_CLKGR, 19 }, 297 }, 298 299 [JZ4755_CLK_TSSI] = { 300 "tssi", CGU_CLK_GATE, 301 .parents = { JZ4755_CLK_EXT_HALF/* not sure */, }, 302 .gate = { CGU_REG_CLKGR, 17 }, 303 }, 304 305 [JZ4755_CLK_IPU] = { 306 "ipu", CGU_CLK_GATE, 307 .parents = { JZ4755_CLK_PLL_HALF/* not sure */, }, 308 .gate = { CGU_REG_CLKGR, 13 }, 309 }, 310 311 [JZ4755_CLK_EXT512] = { 312 "ext/512", CGU_CLK_FIXDIV, 313 .parents = { JZ4755_CLK_EXT, }, 314 315 .fixdiv = { 512 }, 316 }, 317 318 [JZ4755_CLK_UDC_PHY] = { 319 "udc_phy", CGU_CLK_GATE, 320 .parents = { JZ4755_CLK_EXT_HALF, }, 321 .gate = { CGU_REG_OPCR, 6, true }, 322 }, 323 }; 324 325 static void __init jz4755_cgu_init(struct device_node *np) 326 { 327 int retval; 328 329 cgu = ingenic_cgu_new(jz4755_cgu_clocks, 330 ARRAY_SIZE(jz4755_cgu_clocks), np); 331 if (!cgu) { 332 pr_err("%s: failed to initialise CGU\n", __func__); 333 return; 334 } 335 336 retval = ingenic_cgu_register_clocks(cgu); 337 if (retval) 338 pr_err("%s: failed to register CGU Clocks\n", __func__); 339 340 ingenic_cgu_register_syscore_ops(cgu); 341 } 342 /* 343 * CGU has some children devices, this is useful for probing children devices 344 * in the case where the device node is compatible with "simple-mfd". 345 */ 346 CLK_OF_DECLARE_DRIVER(jz4755_cgu, "ingenic,jz4755-cgu", jz4755_cgu_init); 347