Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * X1000 SoC CGU driver
0004  * Copyright (c) 2019 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
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 /* CGU register offsets */
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 /* bits within the OPCR register */
0044 #define OPCR_SPENDN0        BIT(7)
0045 #define OPCR_SPENDN1        BIT(6)
0046 
0047 /* bits within the USBPCR register */
0048 #define USBPCR_SIDDQ        BIT(21)
0049 #define USBPCR_OTG_DISABLE  BIT(20)
0050 
0051 /* bits within the USBPCR1 register */
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     /* External clocks */
0178 
0179     [X1000_CLK_EXCLK] = { "ext", CGU_CLK_EXT },
0180     [X1000_CLK_RTCLK] = { "rtc", CGU_CLK_EXT },
0181 
0182     /* PLLs */
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     /* Custom (SoC-specific) OTG PHY */
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     /* Muxes & dividers */
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          * Disabling the CPU clock or any parent clocks will hang the
0256          * system; mark it critical.
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          * The L2 cache clock is critical if caches are enabled and
0268          * disabling it or any parent clocks will hang the system.
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          * Disabling DDR clock or its parents will render DRAM
0305          * inaccessible; mark it critical.
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     /* Gate-only clocks */
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  * CGU has some children devices, this is useful for probing children devices
0493  * in the case where the device node is compatible with "simple-mfd".
0494  */
0495 CLK_OF_DECLARE_DRIVER(x1000_cgu, "ingenic,x1000-cgu", x1000_cgu_init);