0001
0002
0003
0004
0005
0006
0007 #include <linux/bitops.h>
0008 #include <linux/clk-provider.h>
0009 #include <linux/delay.h>
0010 #include <linux/io.h>
0011 #include <linux/of.h>
0012
0013 #include <linux/clk.h>
0014
0015 #include <dt-bindings/clock/ingenic,jz4760-cgu.h>
0016
0017 #include "cgu.h"
0018 #include "pm.h"
0019
0020 #define MHZ (1000 * 1000)
0021
0022
0023
0024
0025 #define CGU_REG_CPCCR 0x00
0026 #define CGU_REG_LCR 0x04
0027 #define CGU_REG_CPPCR0 0x10
0028 #define CGU_REG_CLKGR0 0x20
0029 #define CGU_REG_OPCR 0x24
0030 #define CGU_REG_CLKGR1 0x28
0031 #define CGU_REG_CPPCR1 0x30
0032 #define CGU_REG_USBPCR 0x3c
0033 #define CGU_REG_USBCDR 0x50
0034 #define CGU_REG_I2SCDR 0x60
0035 #define CGU_REG_LPCDR 0x64
0036 #define CGU_REG_MSCCDR 0x68
0037 #define CGU_REG_UHCCDR 0x6c
0038 #define CGU_REG_SSICDR 0x74
0039 #define CGU_REG_CIMCDR 0x7c
0040 #define CGU_REG_GPSCDR 0x80
0041 #define CGU_REG_PCMCDR 0x84
0042 #define CGU_REG_GPUCDR 0x88
0043
0044 static const s8 pll_od_encoding[8] = {
0045 0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3,
0046 };
0047
0048 static const u8 jz4760_cgu_cpccr_div_table[] = {
0049 1, 2, 3, 4, 6, 8,
0050 };
0051
0052 static const u8 jz4760_cgu_pll_half_div_table[] = {
0053 2, 1,
0054 };
0055
0056 static void
0057 jz4760_cgu_calc_m_n_od(const struct ingenic_cgu_pll_info *pll_info,
0058 unsigned long rate, unsigned long parent_rate,
0059 unsigned int *pm, unsigned int *pn, unsigned int *pod)
0060 {
0061 unsigned int m, n, od, m_max = (1 << pll_info->m_bits) - 2;
0062
0063
0064 n = parent_rate / (1 * MHZ);
0065
0066
0067 n = clamp_val(n, 2, 1 << pll_info->n_bits);
0068
0069 for (;; n >>= 1) {
0070 od = (unsigned int)-1;
0071
0072 do {
0073 m = (rate / MHZ) * (1 << ++od) * n / (parent_rate / MHZ);
0074 } while ((m > m_max || m & 1) && (od < 4));
0075
0076 if (od < 4 && m >= 4 && m <= m_max)
0077 break;
0078 }
0079
0080 *pm = m;
0081 *pn = n;
0082 *pod = 1 << od;
0083 }
0084
0085 static const struct ingenic_cgu_clk_info jz4760_cgu_clocks[] = {
0086
0087
0088
0089 [JZ4760_CLK_EXT] = { "ext", CGU_CLK_EXT },
0090 [JZ4760_CLK_OSC32K] = { "osc32k", CGU_CLK_EXT },
0091
0092
0093
0094 [JZ4760_CLK_PLL0] = {
0095 "pll0", CGU_CLK_PLL,
0096 .parents = { JZ4760_CLK_EXT },
0097 .pll = {
0098 .reg = CGU_REG_CPPCR0,
0099 .rate_multiplier = 1,
0100 .m_shift = 23,
0101 .m_bits = 8,
0102 .m_offset = 0,
0103 .n_shift = 18,
0104 .n_bits = 4,
0105 .n_offset = 0,
0106 .od_shift = 16,
0107 .od_bits = 2,
0108 .od_max = 8,
0109 .od_encoding = pll_od_encoding,
0110 .bypass_reg = CGU_REG_CPPCR0,
0111 .bypass_bit = 9,
0112 .enable_bit = 8,
0113 .stable_bit = 10,
0114 .calc_m_n_od = jz4760_cgu_calc_m_n_od,
0115 },
0116 },
0117
0118 [JZ4760_CLK_PLL1] = {
0119
0120 "pll1", CGU_CLK_PLL,
0121 .parents = { JZ4760_CLK_EXT },
0122 .pll = {
0123 .reg = CGU_REG_CPPCR1,
0124 .rate_multiplier = 1,
0125 .m_shift = 23,
0126 .m_bits = 8,
0127 .m_offset = 0,
0128 .n_shift = 18,
0129 .n_bits = 4,
0130 .n_offset = 0,
0131 .od_shift = 16,
0132 .od_bits = 2,
0133 .od_max = 8,
0134 .od_encoding = pll_od_encoding,
0135 .bypass_bit = -1,
0136 .enable_bit = 7,
0137 .stable_bit = 6,
0138 .calc_m_n_od = jz4760_cgu_calc_m_n_od,
0139 },
0140 },
0141
0142
0143
0144 [JZ4760_CLK_CCLK] = {
0145 "cclk", CGU_CLK_DIV,
0146
0147
0148
0149
0150 .flags = CLK_IS_CRITICAL,
0151 .parents = { JZ4760_CLK_PLL0, },
0152 .div = {
0153 CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, 0,
0154 jz4760_cgu_cpccr_div_table,
0155 },
0156 },
0157 [JZ4760_CLK_HCLK] = {
0158 "hclk", CGU_CLK_DIV,
0159 .parents = { JZ4760_CLK_PLL0, },
0160 .div = {
0161 CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, 0,
0162 jz4760_cgu_cpccr_div_table,
0163 },
0164 },
0165 [JZ4760_CLK_SCLK] = {
0166 "sclk", CGU_CLK_DIV,
0167 .parents = { JZ4760_CLK_PLL0, },
0168 .div = {
0169 CGU_REG_CPCCR, 24, 1, 4, 22, -1, -1, 0,
0170 jz4760_cgu_cpccr_div_table,
0171 },
0172 },
0173 [JZ4760_CLK_H2CLK] = {
0174 "h2clk", CGU_CLK_DIV,
0175 .parents = { JZ4760_CLK_PLL0, },
0176 .div = {
0177 CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1, 0,
0178 jz4760_cgu_cpccr_div_table,
0179 },
0180 },
0181 [JZ4760_CLK_MCLK] = {
0182 "mclk", CGU_CLK_DIV,
0183
0184
0185
0186
0187 .flags = CLK_IS_CRITICAL,
0188 .parents = { JZ4760_CLK_PLL0, },
0189 .div = {
0190 CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, 0,
0191 jz4760_cgu_cpccr_div_table,
0192 },
0193 },
0194 [JZ4760_CLK_PCLK] = {
0195 "pclk", CGU_CLK_DIV,
0196 .parents = { JZ4760_CLK_PLL0, },
0197 .div = {
0198 CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, 0,
0199 jz4760_cgu_cpccr_div_table,
0200 },
0201 },
0202
0203
0204
0205 [JZ4760_CLK_PLL0_HALF] = {
0206 "pll0_half", CGU_CLK_DIV,
0207 .parents = { JZ4760_CLK_PLL0 },
0208 .div = {
0209 CGU_REG_CPCCR, 21, 1, 1, 22, -1, -1, 0,
0210 jz4760_cgu_pll_half_div_table,
0211 },
0212 },
0213
0214
0215
0216 [JZ4760_CLK_UHC] = {
0217 "uhc", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
0218 .parents = { JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1, },
0219 .mux = { CGU_REG_UHCCDR, 31, 1 },
0220 .div = { CGU_REG_UHCCDR, 0, 1, 4, -1, -1, -1 },
0221 .gate = { CGU_REG_CLKGR0, 24 },
0222 },
0223 [JZ4760_CLK_GPU] = {
0224 "gpu", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
0225 .parents = { JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1, },
0226 .mux = { CGU_REG_GPUCDR, 31, 1 },
0227 .div = { CGU_REG_GPUCDR, 0, 1, 3, -1, -1, -1 },
0228 .gate = { CGU_REG_CLKGR1, 9 },
0229 },
0230 [JZ4760_CLK_LPCLK_DIV] = {
0231 "lpclk_div", CGU_CLK_DIV | CGU_CLK_MUX,
0232 .parents = { JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1, },
0233 .mux = { CGU_REG_LPCDR, 29, 1 },
0234 .div = { CGU_REG_LPCDR, 0, 1, 11, -1, -1, -1 },
0235 },
0236 [JZ4760_CLK_TVE] = {
0237 "tve", CGU_CLK_GATE | CGU_CLK_MUX,
0238 .parents = { JZ4760_CLK_LPCLK_DIV, JZ4760_CLK_EXT, },
0239 .mux = { CGU_REG_LPCDR, 31, 1 },
0240 .gate = { CGU_REG_CLKGR0, 27 },
0241 },
0242 [JZ4760_CLK_LPCLK] = {
0243 "lpclk", CGU_CLK_GATE | CGU_CLK_MUX,
0244 .parents = { JZ4760_CLK_LPCLK_DIV, JZ4760_CLK_TVE, },
0245 .mux = { CGU_REG_LPCDR, 30, 1 },
0246 .gate = { CGU_REG_CLKGR0, 28 },
0247 },
0248 [JZ4760_CLK_GPS] = {
0249 "gps", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
0250 .parents = { JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1, },
0251 .mux = { CGU_REG_GPSCDR, 31, 1 },
0252 .div = { CGU_REG_GPSCDR, 0, 1, 4, -1, -1, -1 },
0253 .gate = { CGU_REG_CLKGR0, 22 },
0254 },
0255
0256
0257
0258 [JZ4760_CLK_PCM] = {
0259 "pcm", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
0260 .parents = { JZ4760_CLK_EXT, -1,
0261 JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1 },
0262 .mux = { CGU_REG_PCMCDR, 30, 2 },
0263 .div = { CGU_REG_PCMCDR, 0, 1, 9, -1, -1, -1, BIT(0) },
0264 .gate = { CGU_REG_CLKGR1, 8 },
0265 },
0266 [JZ4760_CLK_I2S] = {
0267 "i2s", CGU_CLK_DIV | CGU_CLK_MUX,
0268 .parents = { JZ4760_CLK_EXT, -1,
0269 JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1 },
0270 .mux = { CGU_REG_I2SCDR, 30, 2 },
0271 .div = { CGU_REG_I2SCDR, 0, 1, 9, -1, -1, -1, BIT(0) },
0272 },
0273 [JZ4760_CLK_OTG] = {
0274 "usb", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
0275 .parents = { JZ4760_CLK_EXT, -1,
0276 JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1 },
0277 .mux = { CGU_REG_USBCDR, 30, 2 },
0278 .div = { CGU_REG_USBCDR, 0, 1, 8, -1, -1, -1 },
0279 .gate = { CGU_REG_CLKGR0, 2 },
0280 },
0281
0282
0283 [JZ4760_CLK_MMC_MUX] = {
0284 "mmc_mux", CGU_CLK_MUX | CGU_CLK_DIV,
0285 .parents = { JZ4760_CLK_EXT, JZ4760_CLK_PLL0_HALF, },
0286 .mux = { CGU_REG_MSCCDR, 31, 1 },
0287 .div = { CGU_REG_MSCCDR, 0, 1, 6, -1, -1, -1, BIT(0) },
0288 },
0289 [JZ4760_CLK_SSI_MUX] = {
0290 "ssi_mux", CGU_CLK_DIV | CGU_CLK_MUX,
0291 .parents = { JZ4760_CLK_EXT, JZ4760_CLK_PLL0_HALF, },
0292 .mux = { CGU_REG_SSICDR, 31, 1 },
0293 .div = { CGU_REG_SSICDR, 0, 1, 6, -1, -1, -1, BIT(0) },
0294 },
0295
0296
0297 [JZ4760_CLK_CIM] = {
0298 "cim", CGU_CLK_DIV | CGU_CLK_GATE,
0299 .parents = { JZ4760_CLK_PLL0_HALF },
0300 .div = { CGU_REG_CIMCDR, 0, 1, 8, -1, -1, -1 },
0301 .gate = { CGU_REG_CLKGR0, 26 },
0302 },
0303
0304
0305
0306 [JZ4760_CLK_SSI0] = {
0307 "ssi0", CGU_CLK_GATE,
0308 .parents = { JZ4760_CLK_SSI_MUX, },
0309 .gate = { CGU_REG_CLKGR0, 4 },
0310 },
0311 [JZ4760_CLK_SSI1] = {
0312 "ssi1", CGU_CLK_GATE,
0313 .parents = { JZ4760_CLK_SSI_MUX, },
0314 .gate = { CGU_REG_CLKGR0, 19 },
0315 },
0316 [JZ4760_CLK_SSI2] = {
0317 "ssi2", CGU_CLK_GATE,
0318 .parents = { JZ4760_CLK_SSI_MUX, },
0319 .gate = { CGU_REG_CLKGR0, 20 },
0320 },
0321 [JZ4760_CLK_DMA] = {
0322 "dma", CGU_CLK_GATE,
0323 .parents = { JZ4760_CLK_H2CLK, },
0324 .gate = { CGU_REG_CLKGR0, 21 },
0325 },
0326 [JZ4760_CLK_MDMA] = {
0327 "mdma", CGU_CLK_GATE,
0328 .parents = { JZ4760_CLK_HCLK, },
0329 .gate = { CGU_REG_CLKGR0, 25 },
0330 },
0331 [JZ4760_CLK_BDMA] = {
0332 "bdma", CGU_CLK_GATE,
0333 .parents = { JZ4760_CLK_HCLK, },
0334 .gate = { CGU_REG_CLKGR1, 0 },
0335 },
0336 [JZ4760_CLK_I2C0] = {
0337 "i2c0", CGU_CLK_GATE,
0338 .parents = { JZ4760_CLK_EXT, },
0339 .gate = { CGU_REG_CLKGR0, 5 },
0340 },
0341 [JZ4760_CLK_I2C1] = {
0342 "i2c1", CGU_CLK_GATE,
0343 .parents = { JZ4760_CLK_EXT, },
0344 .gate = { CGU_REG_CLKGR0, 6 },
0345 },
0346 [JZ4760_CLK_UART0] = {
0347 "uart0", CGU_CLK_GATE,
0348 .parents = { JZ4760_CLK_EXT, },
0349 .gate = { CGU_REG_CLKGR0, 15 },
0350 },
0351 [JZ4760_CLK_UART1] = {
0352 "uart1", CGU_CLK_GATE,
0353 .parents = { JZ4760_CLK_EXT, },
0354 .gate = { CGU_REG_CLKGR0, 16 },
0355 },
0356 [JZ4760_CLK_UART2] = {
0357 "uart2", CGU_CLK_GATE,
0358 .parents = { JZ4760_CLK_EXT, },
0359 .gate = { CGU_REG_CLKGR0, 17 },
0360 },
0361 [JZ4760_CLK_UART3] = {
0362 "uart3", CGU_CLK_GATE,
0363 .parents = { JZ4760_CLK_EXT, },
0364 .gate = { CGU_REG_CLKGR0, 18 },
0365 },
0366 [JZ4760_CLK_IPU] = {
0367 "ipu", CGU_CLK_GATE,
0368 .parents = { JZ4760_CLK_HCLK, },
0369 .gate = { CGU_REG_CLKGR0, 29 },
0370 },
0371 [JZ4760_CLK_ADC] = {
0372 "adc", CGU_CLK_GATE,
0373 .parents = { JZ4760_CLK_EXT, },
0374 .gate = { CGU_REG_CLKGR0, 14 },
0375 },
0376 [JZ4760_CLK_AIC] = {
0377 "aic", CGU_CLK_GATE,
0378 .parents = { JZ4760_CLK_EXT, },
0379 .gate = { CGU_REG_CLKGR0, 8 },
0380 },
0381 [JZ4760_CLK_VPU] = {
0382 "vpu", CGU_CLK_GATE,
0383 .parents = { JZ4760_CLK_HCLK, },
0384 .gate = { CGU_REG_LCR, 30, false, 150 },
0385 },
0386 [JZ4760_CLK_MMC0] = {
0387 "mmc0", CGU_CLK_GATE,
0388 .parents = { JZ4760_CLK_MMC_MUX, },
0389 .gate = { CGU_REG_CLKGR0, 3 },
0390 },
0391 [JZ4760_CLK_MMC1] = {
0392 "mmc1", CGU_CLK_GATE,
0393 .parents = { JZ4760_CLK_MMC_MUX, },
0394 .gate = { CGU_REG_CLKGR0, 11 },
0395 },
0396 [JZ4760_CLK_MMC2] = {
0397 "mmc2", CGU_CLK_GATE,
0398 .parents = { JZ4760_CLK_MMC_MUX, },
0399 .gate = { CGU_REG_CLKGR0, 12 },
0400 },
0401 [JZ4760_CLK_UHC_PHY] = {
0402 "uhc_phy", CGU_CLK_GATE,
0403 .parents = { JZ4760_CLK_UHC, },
0404 .gate = { CGU_REG_OPCR, 5 },
0405 },
0406 [JZ4760_CLK_OTG_PHY] = {
0407 "usb_phy", CGU_CLK_GATE,
0408 .parents = { JZ4760_CLK_OTG },
0409 .gate = { CGU_REG_OPCR, 7, true, 50 },
0410 },
0411
0412
0413 [JZ4760_CLK_EXT512] = {
0414 "ext/512", CGU_CLK_FIXDIV,
0415 .parents = { JZ4760_CLK_EXT },
0416 .fixdiv = { 512 },
0417 },
0418 [JZ4760_CLK_RTC] = {
0419 "rtc", CGU_CLK_MUX,
0420 .parents = { JZ4760_CLK_EXT512, JZ4760_CLK_OSC32K, },
0421 .mux = { CGU_REG_OPCR, 2, 1},
0422 },
0423 };
0424
0425 static void __init jz4760_cgu_init(struct device_node *np)
0426 {
0427 struct ingenic_cgu *cgu;
0428 int retval;
0429
0430 cgu = ingenic_cgu_new(jz4760_cgu_clocks,
0431 ARRAY_SIZE(jz4760_cgu_clocks), np);
0432 if (!cgu) {
0433 pr_err("%s: failed to initialise CGU\n", __func__);
0434 return;
0435 }
0436
0437 retval = ingenic_cgu_register_clocks(cgu);
0438 if (retval)
0439 pr_err("%s: failed to register CGU Clocks\n", __func__);
0440
0441 ingenic_cgu_register_syscore_ops(cgu);
0442 }
0443
0444
0445 CLK_OF_DECLARE_DRIVER(jz4760_cgu, "ingenic,jz4760-cgu", jz4760_cgu_init);
0446
0447
0448 CLK_OF_DECLARE_DRIVER(jz4760b_cgu, "ingenic,jz4760b-cgu", jz4760_cgu_init);