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 <dt-bindings/clock/ingenic,jz4770-cgu.h>
0014
0015 #include "cgu.h"
0016 #include "pm.h"
0017
0018
0019
0020
0021 #define CGU_REG_CPCCR 0x00
0022 #define CGU_REG_LCR 0x04
0023 #define CGU_REG_CPPCR0 0x10
0024 #define CGU_REG_CLKGR0 0x20
0025 #define CGU_REG_OPCR 0x24
0026 #define CGU_REG_CLKGR1 0x28
0027 #define CGU_REG_CPPCR1 0x30
0028 #define CGU_REG_USBPCR1 0x48
0029 #define CGU_REG_USBCDR 0x50
0030 #define CGU_REG_I2SCDR 0x60
0031 #define CGU_REG_LPCDR 0x64
0032 #define CGU_REG_MSC0CDR 0x68
0033 #define CGU_REG_UHCCDR 0x6c
0034 #define CGU_REG_SSICDR 0x74
0035 #define CGU_REG_CIMCDR 0x7c
0036 #define CGU_REG_GPSCDR 0x80
0037 #define CGU_REG_PCMCDR 0x84
0038 #define CGU_REG_GPUCDR 0x88
0039 #define CGU_REG_MSC1CDR 0xA4
0040 #define CGU_REG_MSC2CDR 0xA8
0041 #define CGU_REG_BCHCDR 0xAC
0042
0043
0044 #define OPCR_SPENDH BIT(5)
0045
0046
0047 #define USBPCR1_UHC_POWER BIT(5)
0048
0049 static struct ingenic_cgu *cgu;
0050
0051 static int jz4770_uhc_phy_enable(struct clk_hw *hw)
0052 {
0053 void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
0054 void __iomem *reg_usbpcr1 = cgu->base + CGU_REG_USBPCR1;
0055
0056 writel(readl(reg_opcr) & ~OPCR_SPENDH, reg_opcr);
0057 writel(readl(reg_usbpcr1) | USBPCR1_UHC_POWER, reg_usbpcr1);
0058 return 0;
0059 }
0060
0061 static void jz4770_uhc_phy_disable(struct clk_hw *hw)
0062 {
0063 void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
0064 void __iomem *reg_usbpcr1 = cgu->base + CGU_REG_USBPCR1;
0065
0066 writel(readl(reg_usbpcr1) & ~USBPCR1_UHC_POWER, reg_usbpcr1);
0067 writel(readl(reg_opcr) | OPCR_SPENDH, reg_opcr);
0068 }
0069
0070 static int jz4770_uhc_phy_is_enabled(struct clk_hw *hw)
0071 {
0072 void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
0073 void __iomem *reg_usbpcr1 = cgu->base + CGU_REG_USBPCR1;
0074
0075 return !(readl(reg_opcr) & OPCR_SPENDH) &&
0076 (readl(reg_usbpcr1) & USBPCR1_UHC_POWER);
0077 }
0078
0079 static const struct clk_ops jz4770_uhc_phy_ops = {
0080 .enable = jz4770_uhc_phy_enable,
0081 .disable = jz4770_uhc_phy_disable,
0082 .is_enabled = jz4770_uhc_phy_is_enabled,
0083 };
0084
0085 static const s8 pll_od_encoding[8] = {
0086 0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3,
0087 };
0088
0089 static const u8 jz4770_cgu_cpccr_div_table[] = {
0090 1, 2, 3, 4, 6, 8, 12,
0091 };
0092
0093 static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = {
0094
0095
0096
0097 [JZ4770_CLK_EXT] = { "ext", CGU_CLK_EXT },
0098 [JZ4770_CLK_OSC32K] = { "osc32k", CGU_CLK_EXT },
0099
0100
0101
0102 [JZ4770_CLK_PLL0] = {
0103 "pll0", CGU_CLK_PLL,
0104 .parents = { JZ4770_CLK_EXT },
0105 .pll = {
0106 .reg = CGU_REG_CPPCR0,
0107 .rate_multiplier = 1,
0108 .m_shift = 24,
0109 .m_bits = 7,
0110 .m_offset = 1,
0111 .n_shift = 18,
0112 .n_bits = 5,
0113 .n_offset = 1,
0114 .od_shift = 16,
0115 .od_bits = 2,
0116 .od_max = 8,
0117 .od_encoding = pll_od_encoding,
0118 .bypass_reg = CGU_REG_CPPCR0,
0119 .bypass_bit = 9,
0120 .enable_bit = 8,
0121 .stable_bit = 10,
0122 },
0123 },
0124
0125 [JZ4770_CLK_PLL1] = {
0126
0127 "pll1", CGU_CLK_PLL,
0128 .parents = { JZ4770_CLK_EXT },
0129 .pll = {
0130 .reg = CGU_REG_CPPCR1,
0131 .rate_multiplier = 1,
0132 .m_shift = 24,
0133 .m_bits = 7,
0134 .m_offset = 1,
0135 .n_shift = 18,
0136 .n_bits = 5,
0137 .n_offset = 1,
0138 .od_shift = 16,
0139 .od_bits = 2,
0140 .od_max = 8,
0141 .od_encoding = pll_od_encoding,
0142 .bypass_bit = -1,
0143 .enable_bit = 7,
0144 .stable_bit = 6,
0145 },
0146 },
0147
0148
0149
0150 [JZ4770_CLK_CCLK] = {
0151 "cclk", CGU_CLK_DIV,
0152
0153
0154
0155
0156 .flags = CLK_IS_CRITICAL,
0157 .parents = { JZ4770_CLK_PLL0, },
0158 .div = {
0159 CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, 0,
0160 jz4770_cgu_cpccr_div_table,
0161 },
0162 },
0163 [JZ4770_CLK_H0CLK] = {
0164 "h0clk", CGU_CLK_DIV,
0165 .parents = { JZ4770_CLK_PLL0, },
0166 .div = {
0167 CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, 0,
0168 jz4770_cgu_cpccr_div_table,
0169 },
0170 },
0171 [JZ4770_CLK_H1CLK] = {
0172 "h1clk", CGU_CLK_DIV | CGU_CLK_GATE,
0173 .parents = { JZ4770_CLK_PLL0, },
0174 .div = {
0175 CGU_REG_CPCCR, 24, 1, 4, 22, -1, -1, 0,
0176 jz4770_cgu_cpccr_div_table,
0177 },
0178 .gate = { CGU_REG_CLKGR1, 7 },
0179 },
0180 [JZ4770_CLK_H2CLK] = {
0181 "h2clk", CGU_CLK_DIV,
0182 .parents = { JZ4770_CLK_PLL0, },
0183 .div = {
0184 CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1, 0,
0185 jz4770_cgu_cpccr_div_table,
0186 },
0187 },
0188 [JZ4770_CLK_C1CLK] = {
0189 "c1clk", CGU_CLK_DIV | CGU_CLK_GATE,
0190 .parents = { JZ4770_CLK_PLL0, },
0191 .div = {
0192 CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, 0,
0193 jz4770_cgu_cpccr_div_table,
0194 },
0195 .gate = { CGU_REG_OPCR, 31, true },
0196 },
0197 [JZ4770_CLK_PCLK] = {
0198 "pclk", CGU_CLK_DIV,
0199 .parents = { JZ4770_CLK_PLL0, },
0200 .div = {
0201 CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, 0,
0202 jz4770_cgu_cpccr_div_table,
0203 },
0204 },
0205
0206
0207
0208 [JZ4770_CLK_MMC0_MUX] = {
0209 "mmc0_mux", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
0210 .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
0211 .mux = { CGU_REG_MSC0CDR, 30, 1 },
0212 .div = { CGU_REG_MSC0CDR, 0, 1, 7, -1, -1, 31 },
0213 .gate = { CGU_REG_MSC0CDR, 31 },
0214 },
0215 [JZ4770_CLK_MMC1_MUX] = {
0216 "mmc1_mux", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
0217 .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
0218 .mux = { CGU_REG_MSC1CDR, 30, 1 },
0219 .div = { CGU_REG_MSC1CDR, 0, 1, 7, -1, -1, 31 },
0220 .gate = { CGU_REG_MSC1CDR, 31 },
0221 },
0222 [JZ4770_CLK_MMC2_MUX] = {
0223 "mmc2_mux", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
0224 .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
0225 .mux = { CGU_REG_MSC2CDR, 30, 1 },
0226 .div = { CGU_REG_MSC2CDR, 0, 1, 7, -1, -1, 31 },
0227 .gate = { CGU_REG_MSC2CDR, 31 },
0228 },
0229 [JZ4770_CLK_CIM] = {
0230 "cim", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
0231 .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
0232 .mux = { CGU_REG_CIMCDR, 31, 1 },
0233 .div = { CGU_REG_CIMCDR, 0, 1, 8, -1, -1, -1 },
0234 .gate = { CGU_REG_CLKGR0, 26 },
0235 },
0236 [JZ4770_CLK_UHC] = {
0237 "uhc", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
0238 .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
0239 .mux = { CGU_REG_UHCCDR, 29, 1 },
0240 .div = { CGU_REG_UHCCDR, 0, 1, 4, -1, -1, -1 },
0241 .gate = { CGU_REG_CLKGR0, 24 },
0242 },
0243 [JZ4770_CLK_GPU] = {
0244 "gpu", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
0245 .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, -1 },
0246 .mux = { CGU_REG_GPUCDR, 31, 1 },
0247 .div = { CGU_REG_GPUCDR, 0, 1, 3, -1, -1, -1 },
0248 .gate = { CGU_REG_CLKGR1, 9 },
0249 },
0250 [JZ4770_CLK_BCH] = {
0251 "bch", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
0252 .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
0253 .mux = { CGU_REG_BCHCDR, 31, 1 },
0254 .div = { CGU_REG_BCHCDR, 0, 1, 3, -1, -1, -1 },
0255 .gate = { CGU_REG_CLKGR0, 1 },
0256 },
0257 [JZ4770_CLK_LPCLK_MUX] = {
0258 "lpclk", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
0259 .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
0260 .mux = { CGU_REG_LPCDR, 29, 1 },
0261 .div = { CGU_REG_LPCDR, 0, 1, 11, -1, -1, -1 },
0262 .gate = { CGU_REG_CLKGR0, 28 },
0263 },
0264 [JZ4770_CLK_GPS] = {
0265 "gps", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
0266 .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
0267 .mux = { CGU_REG_GPSCDR, 31, 1 },
0268 .div = { CGU_REG_GPSCDR, 0, 1, 4, -1, -1, -1 },
0269 .gate = { CGU_REG_CLKGR0, 22 },
0270 },
0271
0272
0273
0274 [JZ4770_CLK_SSI_MUX] = {
0275 "ssi_mux", CGU_CLK_DIV | CGU_CLK_MUX,
0276 .parents = { JZ4770_CLK_EXT, -1,
0277 JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 },
0278 .mux = { CGU_REG_SSICDR, 30, 2 },
0279 .div = { CGU_REG_SSICDR, 0, 1, 6, -1, -1, -1 },
0280 },
0281 [JZ4770_CLK_PCM_MUX] = {
0282 "pcm_mux", CGU_CLK_DIV | CGU_CLK_MUX,
0283 .parents = { JZ4770_CLK_EXT, -1,
0284 JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 },
0285 .mux = { CGU_REG_PCMCDR, 30, 2 },
0286 .div = { CGU_REG_PCMCDR, 0, 1, 9, -1, -1, -1 },
0287 },
0288 [JZ4770_CLK_I2S] = {
0289 "i2s", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
0290 .parents = { JZ4770_CLK_EXT, -1,
0291 JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 },
0292 .mux = { CGU_REG_I2SCDR, 30, 2 },
0293 .div = { CGU_REG_I2SCDR, 0, 1, 9, -1, -1, -1 },
0294 .gate = { CGU_REG_CLKGR1, 13 },
0295 },
0296 [JZ4770_CLK_OTG] = {
0297 "usb", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
0298 .parents = { JZ4770_CLK_EXT, -1,
0299 JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 },
0300 .mux = { CGU_REG_USBCDR, 30, 2 },
0301 .div = { CGU_REG_USBCDR, 0, 1, 8, -1, -1, -1 },
0302 .gate = { CGU_REG_CLKGR0, 2 },
0303 },
0304
0305
0306
0307 [JZ4770_CLK_SSI0] = {
0308 "ssi0", CGU_CLK_GATE,
0309 .parents = { JZ4770_CLK_SSI_MUX, },
0310 .gate = { CGU_REG_CLKGR0, 4 },
0311 },
0312 [JZ4770_CLK_SSI1] = {
0313 "ssi1", CGU_CLK_GATE,
0314 .parents = { JZ4770_CLK_SSI_MUX, },
0315 .gate = { CGU_REG_CLKGR0, 19 },
0316 },
0317 [JZ4770_CLK_SSI2] = {
0318 "ssi2", CGU_CLK_GATE,
0319 .parents = { JZ4770_CLK_SSI_MUX, },
0320 .gate = { CGU_REG_CLKGR0, 20 },
0321 },
0322 [JZ4770_CLK_PCM0] = {
0323 "pcm0", CGU_CLK_GATE,
0324 .parents = { JZ4770_CLK_PCM_MUX, },
0325 .gate = { CGU_REG_CLKGR1, 8 },
0326 },
0327 [JZ4770_CLK_PCM1] = {
0328 "pcm1", CGU_CLK_GATE,
0329 .parents = { JZ4770_CLK_PCM_MUX, },
0330 .gate = { CGU_REG_CLKGR1, 10 },
0331 },
0332 [JZ4770_CLK_DMA] = {
0333 "dma", CGU_CLK_GATE,
0334 .parents = { JZ4770_CLK_H2CLK, },
0335 .gate = { CGU_REG_CLKGR0, 21 },
0336 },
0337 [JZ4770_CLK_BDMA] = {
0338 "bdma", CGU_CLK_GATE,
0339 .parents = { JZ4770_CLK_H2CLK, },
0340 .gate = { CGU_REG_CLKGR1, 0 },
0341 },
0342 [JZ4770_CLK_I2C0] = {
0343 "i2c0", CGU_CLK_GATE,
0344 .parents = { JZ4770_CLK_EXT, },
0345 .gate = { CGU_REG_CLKGR0, 5 },
0346 },
0347 [JZ4770_CLK_I2C1] = {
0348 "i2c1", CGU_CLK_GATE,
0349 .parents = { JZ4770_CLK_EXT, },
0350 .gate = { CGU_REG_CLKGR0, 6 },
0351 },
0352 [JZ4770_CLK_I2C2] = {
0353 "i2c2", CGU_CLK_GATE,
0354 .parents = { JZ4770_CLK_EXT, },
0355 .gate = { CGU_REG_CLKGR1, 15 },
0356 },
0357 [JZ4770_CLK_UART0] = {
0358 "uart0", CGU_CLK_GATE,
0359 .parents = { JZ4770_CLK_EXT, },
0360 .gate = { CGU_REG_CLKGR0, 15 },
0361 },
0362 [JZ4770_CLK_UART1] = {
0363 "uart1", CGU_CLK_GATE,
0364 .parents = { JZ4770_CLK_EXT, },
0365 .gate = { CGU_REG_CLKGR0, 16 },
0366 },
0367 [JZ4770_CLK_UART2] = {
0368 "uart2", CGU_CLK_GATE,
0369 .parents = { JZ4770_CLK_EXT, },
0370 .gate = { CGU_REG_CLKGR0, 17 },
0371 },
0372 [JZ4770_CLK_UART3] = {
0373 "uart3", CGU_CLK_GATE,
0374 .parents = { JZ4770_CLK_EXT, },
0375 .gate = { CGU_REG_CLKGR0, 18 },
0376 },
0377 [JZ4770_CLK_IPU] = {
0378 "ipu", CGU_CLK_GATE,
0379 .parents = { JZ4770_CLK_H0CLK, },
0380 .gate = { CGU_REG_CLKGR0, 29 },
0381 },
0382 [JZ4770_CLK_ADC] = {
0383 "adc", CGU_CLK_GATE,
0384 .parents = { JZ4770_CLK_EXT, },
0385 .gate = { CGU_REG_CLKGR0, 14 },
0386 },
0387 [JZ4770_CLK_AIC] = {
0388 "aic", CGU_CLK_GATE,
0389 .parents = { JZ4770_CLK_EXT, },
0390 .gate = { CGU_REG_CLKGR0, 8 },
0391 },
0392 [JZ4770_CLK_AUX] = {
0393 "aux", CGU_CLK_GATE,
0394 .parents = { JZ4770_CLK_C1CLK, },
0395 .gate = { CGU_REG_CLKGR1, 14 },
0396 },
0397 [JZ4770_CLK_VPU] = {
0398 "vpu", CGU_CLK_GATE,
0399 .parents = { JZ4770_CLK_H1CLK, },
0400 .gate = { CGU_REG_LCR, 30, false, 150 },
0401 },
0402 [JZ4770_CLK_MMC0] = {
0403 "mmc0", CGU_CLK_GATE,
0404 .parents = { JZ4770_CLK_MMC0_MUX, },
0405 .gate = { CGU_REG_CLKGR0, 3 },
0406 },
0407 [JZ4770_CLK_MMC1] = {
0408 "mmc1", CGU_CLK_GATE,
0409 .parents = { JZ4770_CLK_MMC1_MUX, },
0410 .gate = { CGU_REG_CLKGR0, 11 },
0411 },
0412 [JZ4770_CLK_MMC2] = {
0413 "mmc2", CGU_CLK_GATE,
0414 .parents = { JZ4770_CLK_MMC2_MUX, },
0415 .gate = { CGU_REG_CLKGR0, 12 },
0416 },
0417 [JZ4770_CLK_OTG_PHY] = {
0418 "usb_phy", CGU_CLK_GATE,
0419 .parents = { JZ4770_CLK_OTG },
0420 .gate = { CGU_REG_OPCR, 7, true, 50 },
0421 },
0422
0423
0424
0425 [JZ4770_CLK_UHC_PHY] = {
0426 "uhc_phy", CGU_CLK_CUSTOM,
0427 .parents = { JZ4770_CLK_UHC, -1, -1, -1 },
0428 .custom = { &jz4770_uhc_phy_ops },
0429 },
0430
0431 [JZ4770_CLK_EXT512] = {
0432 "ext/512", CGU_CLK_FIXDIV,
0433 .parents = { JZ4770_CLK_EXT },
0434 .fixdiv = { 512 },
0435 },
0436
0437 [JZ4770_CLK_RTC] = {
0438 "rtc", CGU_CLK_MUX,
0439 .parents = { JZ4770_CLK_EXT512, JZ4770_CLK_OSC32K, },
0440 .mux = { CGU_REG_OPCR, 2, 1},
0441 },
0442 };
0443
0444 static void __init jz4770_cgu_init(struct device_node *np)
0445 {
0446 int retval;
0447
0448 cgu = ingenic_cgu_new(jz4770_cgu_clocks,
0449 ARRAY_SIZE(jz4770_cgu_clocks), np);
0450 if (!cgu) {
0451 pr_err("%s: failed to initialise CGU\n", __func__);
0452 return;
0453 }
0454
0455 retval = ingenic_cgu_register_clocks(cgu);
0456 if (retval)
0457 pr_err("%s: failed to register CGU Clocks\n", __func__);
0458
0459 ingenic_cgu_register_syscore_ops(cgu);
0460 }
0461
0462
0463 CLK_OF_DECLARE_DRIVER(jz4770_cgu, "ingenic,jz4770-cgu", jz4770_cgu_init);