0001
0002
0003
0004
0005
0006
0007 #include <linux/clk-provider.h>
0008 #include <linux/delay.h>
0009 #include <linux/io.h>
0010 #include <linux/of.h>
0011
0012 #include <dt-bindings/clock/ingenic,x1000-cgu.h>
0013
0014 #include "cgu.h"
0015 #include "pm.h"
0016
0017
0018 #define CGU_REG_CPCCR 0x00
0019 #define CGU_REG_APLL 0x10
0020 #define CGU_REG_MPLL 0x14
0021 #define CGU_REG_CLKGR 0x20
0022 #define CGU_REG_OPCR 0x24
0023 #define CGU_REG_DDRCDR 0x2c
0024 #define CGU_REG_USBPCR 0x3c
0025 #define CGU_REG_USBPCR1 0x48
0026 #define CGU_REG_USBCDR 0x50
0027 #define CGU_REG_MACCDR 0x54
0028 #define CGU_REG_I2SCDR 0x60
0029 #define CGU_REG_LPCDR 0x64
0030 #define CGU_REG_MSC0CDR 0x68
0031 #define CGU_REG_I2SCDR1 0x70
0032 #define CGU_REG_SSICDR 0x74
0033 #define CGU_REG_CIMCDR 0x7c
0034 #define CGU_REG_PCMCDR 0x84
0035 #define CGU_REG_MSC1CDR 0xa4
0036 #define CGU_REG_CMP_INTR 0xb0
0037 #define CGU_REG_CMP_INTRE 0xb4
0038 #define CGU_REG_DRCG 0xd0
0039 #define CGU_REG_CPCSR 0xd4
0040 #define CGU_REG_PCMCDR1 0xe0
0041 #define CGU_REG_MACPHYC 0xe8
0042
0043
0044 #define OPCR_SPENDN0 BIT(7)
0045 #define OPCR_SPENDN1 BIT(6)
0046
0047
0048 #define USBPCR_SIDDQ BIT(21)
0049 #define USBPCR_OTG_DISABLE BIT(20)
0050
0051
0052 #define USBPCR1_REFCLKSEL_SHIFT 26
0053 #define USBPCR1_REFCLKSEL_MASK (0x3 << USBPCR1_REFCLKSEL_SHIFT)
0054 #define USBPCR1_REFCLKSEL_CORE (0x2 << USBPCR1_REFCLKSEL_SHIFT)
0055 #define USBPCR1_REFCLKDIV_SHIFT 24
0056 #define USBPCR1_REFCLKDIV_MASK (0x3 << USBPCR1_REFCLKDIV_SHIFT)
0057 #define USBPCR1_REFCLKDIV_48 (0x2 << USBPCR1_REFCLKDIV_SHIFT)
0058 #define USBPCR1_REFCLKDIV_24 (0x1 << USBPCR1_REFCLKDIV_SHIFT)
0059 #define USBPCR1_REFCLKDIV_12 (0x0 << USBPCR1_REFCLKDIV_SHIFT)
0060
0061 static struct ingenic_cgu *cgu;
0062
0063 static unsigned long x1000_otg_phy_recalc_rate(struct clk_hw *hw,
0064 unsigned long parent_rate)
0065 {
0066 u32 usbpcr1;
0067 unsigned refclk_div;
0068
0069 usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
0070 refclk_div = usbpcr1 & USBPCR1_REFCLKDIV_MASK;
0071
0072 switch (refclk_div) {
0073 case USBPCR1_REFCLKDIV_12:
0074 return 12000000;
0075
0076 case USBPCR1_REFCLKDIV_24:
0077 return 24000000;
0078
0079 case USBPCR1_REFCLKDIV_48:
0080 return 48000000;
0081 }
0082
0083 return parent_rate;
0084 }
0085
0086 static long x1000_otg_phy_round_rate(struct clk_hw *hw, unsigned long req_rate,
0087 unsigned long *parent_rate)
0088 {
0089 if (req_rate < 18000000)
0090 return 12000000;
0091
0092 if (req_rate < 36000000)
0093 return 24000000;
0094
0095 return 48000000;
0096 }
0097
0098 static int x1000_otg_phy_set_rate(struct clk_hw *hw, unsigned long req_rate,
0099 unsigned long parent_rate)
0100 {
0101 unsigned long flags;
0102 u32 usbpcr1, div_bits;
0103
0104 switch (req_rate) {
0105 case 12000000:
0106 div_bits = USBPCR1_REFCLKDIV_12;
0107 break;
0108
0109 case 24000000:
0110 div_bits = USBPCR1_REFCLKDIV_24;
0111 break;
0112
0113 case 48000000:
0114 div_bits = USBPCR1_REFCLKDIV_48;
0115 break;
0116
0117 default:
0118 return -EINVAL;
0119 }
0120
0121 spin_lock_irqsave(&cgu->lock, flags);
0122
0123 usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
0124 usbpcr1 &= ~USBPCR1_REFCLKDIV_MASK;
0125 usbpcr1 |= div_bits;
0126 writel(usbpcr1, cgu->base + CGU_REG_USBPCR1);
0127
0128 spin_unlock_irqrestore(&cgu->lock, flags);
0129 return 0;
0130 }
0131
0132 static int x1000_usb_phy_enable(struct clk_hw *hw)
0133 {
0134 void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
0135 void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR;
0136
0137 writel(readl(reg_opcr) | OPCR_SPENDN0, reg_opcr);
0138 writel(readl(reg_usbpcr) & ~USBPCR_OTG_DISABLE & ~USBPCR_SIDDQ, reg_usbpcr);
0139 return 0;
0140 }
0141
0142 static void x1000_usb_phy_disable(struct clk_hw *hw)
0143 {
0144 void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
0145 void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR;
0146
0147 writel(readl(reg_opcr) & ~OPCR_SPENDN0, reg_opcr);
0148 writel(readl(reg_usbpcr) | USBPCR_OTG_DISABLE | USBPCR_SIDDQ, reg_usbpcr);
0149 }
0150
0151 static int x1000_usb_phy_is_enabled(struct clk_hw *hw)
0152 {
0153 void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
0154 void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR;
0155
0156 return (readl(reg_opcr) & OPCR_SPENDN0) &&
0157 !(readl(reg_usbpcr) & USBPCR_SIDDQ) &&
0158 !(readl(reg_usbpcr) & USBPCR_OTG_DISABLE);
0159 }
0160
0161 static const struct clk_ops x1000_otg_phy_ops = {
0162 .recalc_rate = x1000_otg_phy_recalc_rate,
0163 .round_rate = x1000_otg_phy_round_rate,
0164 .set_rate = x1000_otg_phy_set_rate,
0165
0166 .enable = x1000_usb_phy_enable,
0167 .disable = x1000_usb_phy_disable,
0168 .is_enabled = x1000_usb_phy_is_enabled,
0169 };
0170
0171 static const s8 pll_od_encoding[8] = {
0172 0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3,
0173 };
0174
0175 static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
0176
0177
0178
0179 [X1000_CLK_EXCLK] = { "ext", CGU_CLK_EXT },
0180 [X1000_CLK_RTCLK] = { "rtc", CGU_CLK_EXT },
0181
0182
0183
0184 [X1000_CLK_APLL] = {
0185 "apll", CGU_CLK_PLL,
0186 .parents = { X1000_CLK_EXCLK, -1, -1, -1 },
0187 .pll = {
0188 .reg = CGU_REG_APLL,
0189 .rate_multiplier = 1,
0190 .m_shift = 24,
0191 .m_bits = 7,
0192 .m_offset = 1,
0193 .n_shift = 18,
0194 .n_bits = 5,
0195 .n_offset = 1,
0196 .od_shift = 16,
0197 .od_bits = 2,
0198 .od_max = 8,
0199 .od_encoding = pll_od_encoding,
0200 .bypass_reg = CGU_REG_APLL,
0201 .bypass_bit = 9,
0202 .enable_bit = 8,
0203 .stable_bit = 10,
0204 },
0205 },
0206
0207 [X1000_CLK_MPLL] = {
0208 "mpll", CGU_CLK_PLL,
0209 .parents = { X1000_CLK_EXCLK, -1, -1, -1 },
0210 .pll = {
0211 .reg = CGU_REG_MPLL,
0212 .rate_multiplier = 1,
0213 .m_shift = 24,
0214 .m_bits = 7,
0215 .m_offset = 1,
0216 .n_shift = 18,
0217 .n_bits = 5,
0218 .n_offset = 1,
0219 .od_shift = 16,
0220 .od_bits = 2,
0221 .od_max = 8,
0222 .od_encoding = pll_od_encoding,
0223 .bypass_reg = CGU_REG_MPLL,
0224 .bypass_bit = 6,
0225 .enable_bit = 7,
0226 .stable_bit = 0,
0227 },
0228 },
0229
0230
0231
0232 [X1000_CLK_OTGPHY] = {
0233 "otg_phy", CGU_CLK_CUSTOM,
0234 .parents = { -1, -1, X1000_CLK_EXCLK, -1 },
0235 .custom = { &x1000_otg_phy_ops },
0236 },
0237
0238
0239
0240 [X1000_CLK_SCLKA] = {
0241 "sclk_a", CGU_CLK_MUX,
0242 .parents = { -1, X1000_CLK_EXCLK, X1000_CLK_APLL, -1 },
0243 .mux = { CGU_REG_CPCCR, 30, 2 },
0244 },
0245
0246 [X1000_CLK_CPUMUX] = {
0247 "cpu_mux", CGU_CLK_MUX,
0248 .parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 },
0249 .mux = { CGU_REG_CPCCR, 28, 2 },
0250 },
0251
0252 [X1000_CLK_CPU] = {
0253 "cpu", CGU_CLK_DIV | CGU_CLK_GATE,
0254
0255
0256
0257
0258 .flags = CLK_IS_CRITICAL,
0259 .parents = { X1000_CLK_CPUMUX, -1, -1, -1 },
0260 .div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1 },
0261 .gate = { CGU_REG_CLKGR, 30 },
0262 },
0263
0264 [X1000_CLK_L2CACHE] = {
0265 "l2cache", CGU_CLK_DIV,
0266
0267
0268
0269
0270 .flags = CLK_IS_CRITICAL,
0271 .parents = { X1000_CLK_CPUMUX, -1, -1, -1 },
0272 .div = { CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1 },
0273 },
0274
0275 [X1000_CLK_AHB0] = {
0276 "ahb0", CGU_CLK_MUX | CGU_CLK_DIV,
0277 .parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 },
0278 .mux = { CGU_REG_CPCCR, 26, 2 },
0279 .div = { CGU_REG_CPCCR, 8, 1, 4, 21, -1, -1 },
0280 },
0281
0282 [X1000_CLK_AHB2PMUX] = {
0283 "ahb2_apb_mux", CGU_CLK_MUX,
0284 .parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 },
0285 .mux = { CGU_REG_CPCCR, 24, 2 },
0286 },
0287
0288 [X1000_CLK_AHB2] = {
0289 "ahb2", CGU_CLK_DIV,
0290 .parents = { X1000_CLK_AHB2PMUX, -1, -1, -1 },
0291 .div = { CGU_REG_CPCCR, 12, 1, 4, 20, -1, -1 },
0292 },
0293
0294 [X1000_CLK_PCLK] = {
0295 "pclk", CGU_CLK_DIV | CGU_CLK_GATE,
0296 .parents = { X1000_CLK_AHB2PMUX, -1, -1, -1 },
0297 .div = { CGU_REG_CPCCR, 16, 1, 4, 20, -1, -1 },
0298 .gate = { CGU_REG_CLKGR, 28 },
0299 },
0300
0301 [X1000_CLK_DDR] = {
0302 "ddr", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
0303
0304
0305
0306
0307 .flags = CLK_IS_CRITICAL,
0308 .parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 },
0309 .mux = { CGU_REG_DDRCDR, 30, 2 },
0310 .div = { CGU_REG_DDRCDR, 0, 1, 4, 29, 28, 27 },
0311 .gate = { CGU_REG_CLKGR, 31 },
0312 },
0313
0314 [X1000_CLK_MAC] = {
0315 "mac", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
0316 .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL },
0317 .mux = { CGU_REG_MACCDR, 31, 1 },
0318 .div = { CGU_REG_MACCDR, 0, 1, 8, 29, 28, 27 },
0319 .gate = { CGU_REG_CLKGR, 25 },
0320 },
0321
0322 [X1000_CLK_LCD] = {
0323 "lcd", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
0324 .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL },
0325 .mux = { CGU_REG_LPCDR, 31, 1 },
0326 .div = { CGU_REG_LPCDR, 0, 1, 8, 28, 27, 26 },
0327 .gate = { CGU_REG_CLKGR, 23 },
0328 },
0329
0330 [X1000_CLK_MSCMUX] = {
0331 "msc_mux", CGU_CLK_MUX,
0332 .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL},
0333 .mux = { CGU_REG_MSC0CDR, 31, 1 },
0334 },
0335
0336 [X1000_CLK_MSC0] = {
0337 "msc0", CGU_CLK_DIV | CGU_CLK_GATE,
0338 .parents = { X1000_CLK_MSCMUX, -1, -1, -1 },
0339 .div = { CGU_REG_MSC0CDR, 0, 2, 8, 29, 28, 27 },
0340 .gate = { CGU_REG_CLKGR, 4 },
0341 },
0342
0343 [X1000_CLK_MSC1] = {
0344 "msc1", CGU_CLK_DIV | CGU_CLK_GATE,
0345 .parents = { X1000_CLK_MSCMUX, -1, -1, -1 },
0346 .div = { CGU_REG_MSC1CDR, 0, 2, 8, 29, 28, 27 },
0347 .gate = { CGU_REG_CLKGR, 5 },
0348 },
0349
0350 [X1000_CLK_OTG] = {
0351 "otg", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
0352 .parents = { X1000_CLK_EXCLK, -1,
0353 X1000_CLK_APLL, X1000_CLK_MPLL },
0354 .mux = { CGU_REG_USBCDR, 30, 2 },
0355 .div = { CGU_REG_USBCDR, 0, 1, 8, 29, 28, 27 },
0356 .gate = { CGU_REG_CLKGR, 3 },
0357 },
0358
0359 [X1000_CLK_SSIPLL] = {
0360 "ssi_pll", CGU_CLK_MUX | CGU_CLK_DIV,
0361 .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL, -1, -1 },
0362 .mux = { CGU_REG_SSICDR, 31, 1 },
0363 .div = { CGU_REG_SSICDR, 0, 1, 8, 29, 28, 27 },
0364 },
0365
0366 [X1000_CLK_SSIPLL_DIV2] = {
0367 "ssi_pll_div2", CGU_CLK_FIXDIV,
0368 .parents = { X1000_CLK_SSIPLL },
0369 .fixdiv = { 2 },
0370 },
0371
0372 [X1000_CLK_SSIMUX] = {
0373 "ssi_mux", CGU_CLK_MUX,
0374 .parents = { X1000_CLK_EXCLK, X1000_CLK_SSIPLL_DIV2, -1, -1 },
0375 .mux = { CGU_REG_SSICDR, 30, 1 },
0376 },
0377
0378 [X1000_CLK_EXCLK_DIV512] = {
0379 "exclk_div512", CGU_CLK_FIXDIV,
0380 .parents = { X1000_CLK_EXCLK },
0381 .fixdiv = { 512 },
0382 },
0383
0384 [X1000_CLK_RTC] = {
0385 "rtc_ercs", CGU_CLK_MUX | CGU_CLK_GATE,
0386 .parents = { X1000_CLK_EXCLK_DIV512, X1000_CLK_RTCLK },
0387 .mux = { CGU_REG_OPCR, 2, 1},
0388 .gate = { CGU_REG_CLKGR, 27 },
0389 },
0390
0391
0392
0393 [X1000_CLK_EMC] = {
0394 "emc", CGU_CLK_GATE,
0395 .parents = { X1000_CLK_AHB2, -1, -1, -1 },
0396 .gate = { CGU_REG_CLKGR, 0 },
0397 },
0398
0399 [X1000_CLK_EFUSE] = {
0400 "efuse", CGU_CLK_GATE,
0401 .parents = { X1000_CLK_AHB2, -1, -1, -1 },
0402 .gate = { CGU_REG_CLKGR, 1 },
0403 },
0404
0405 [X1000_CLK_SFC] = {
0406 "sfc", CGU_CLK_GATE,
0407 .parents = { X1000_CLK_SSIPLL, -1, -1, -1 },
0408 .gate = { CGU_REG_CLKGR, 2 },
0409 },
0410
0411 [X1000_CLK_I2C0] = {
0412 "i2c0", CGU_CLK_GATE,
0413 .parents = { X1000_CLK_PCLK, -1, -1, -1 },
0414 .gate = { CGU_REG_CLKGR, 7 },
0415 },
0416
0417 [X1000_CLK_I2C1] = {
0418 "i2c1", CGU_CLK_GATE,
0419 .parents = { X1000_CLK_PCLK, -1, -1, -1 },
0420 .gate = { CGU_REG_CLKGR, 8 },
0421 },
0422
0423 [X1000_CLK_I2C2] = {
0424 "i2c2", CGU_CLK_GATE,
0425 .parents = { X1000_CLK_PCLK, -1, -1, -1 },
0426 .gate = { CGU_REG_CLKGR, 9 },
0427 },
0428
0429 [X1000_CLK_UART0] = {
0430 "uart0", CGU_CLK_GATE,
0431 .parents = { X1000_CLK_EXCLK, -1, -1, -1 },
0432 .gate = { CGU_REG_CLKGR, 14 },
0433 },
0434
0435 [X1000_CLK_UART1] = {
0436 "uart1", CGU_CLK_GATE,
0437 .parents = { X1000_CLK_EXCLK, -1, -1, -1 },
0438 .gate = { CGU_REG_CLKGR, 15 },
0439 },
0440
0441 [X1000_CLK_UART2] = {
0442 "uart2", CGU_CLK_GATE,
0443 .parents = { X1000_CLK_EXCLK, -1, -1, -1 },
0444 .gate = { CGU_REG_CLKGR, 16 },
0445 },
0446
0447 [X1000_CLK_TCU] = {
0448 "tcu", CGU_CLK_GATE,
0449 .parents = { X1000_CLK_EXCLK, -1, -1, -1 },
0450 .gate = { CGU_REG_CLKGR, 18 },
0451 },
0452
0453 [X1000_CLK_SSI] = {
0454 "ssi", CGU_CLK_GATE,
0455 .parents = { X1000_CLK_SSIMUX, -1, -1, -1 },
0456 .gate = { CGU_REG_CLKGR, 19 },
0457 },
0458
0459 [X1000_CLK_OST] = {
0460 "ost", CGU_CLK_GATE,
0461 .parents = { X1000_CLK_EXCLK, -1, -1, -1 },
0462 .gate = { CGU_REG_CLKGR, 20 },
0463 },
0464
0465 [X1000_CLK_PDMA] = {
0466 "pdma", CGU_CLK_GATE,
0467 .parents = { X1000_CLK_EXCLK, -1, -1, -1 },
0468 .gate = { CGU_REG_CLKGR, 21 },
0469 },
0470 };
0471
0472 static void __init x1000_cgu_init(struct device_node *np)
0473 {
0474 int retval;
0475
0476 cgu = ingenic_cgu_new(x1000_cgu_clocks,
0477 ARRAY_SIZE(x1000_cgu_clocks), np);
0478 if (!cgu) {
0479 pr_err("%s: failed to initialise CGU\n", __func__);
0480 return;
0481 }
0482
0483 retval = ingenic_cgu_register_clocks(cgu);
0484 if (retval) {
0485 pr_err("%s: failed to register CGU Clocks\n", __func__);
0486 return;
0487 }
0488
0489 ingenic_cgu_register_syscore_ops(cgu);
0490 }
0491
0492
0493
0494
0495 CLK_OF_DECLARE_DRIVER(x1000_cgu, "ingenic,x1000-cgu", x1000_cgu_init);