0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/clk-provider.h>
0010 #include <linux/delay.h>
0011 #include <linux/of.h>
0012
0013 #include <dt-bindings/clock/ingenic,jz4725b-cgu.h>
0014
0015 #include "cgu.h"
0016 #include "pm.h"
0017
0018
0019 #define CGU_REG_CPCCR 0x00
0020 #define CGU_REG_LCR 0x04
0021 #define CGU_REG_CPPCR 0x10
0022 #define CGU_REG_CLKGR 0x20
0023 #define CGU_REG_OPCR 0x24
0024 #define CGU_REG_I2SCDR 0x60
0025 #define CGU_REG_LPCDR 0x64
0026 #define CGU_REG_MSCCDR 0x68
0027 #define CGU_REG_SSICDR 0x74
0028 #define CGU_REG_CIMCDR 0x78
0029
0030
0031 #define LCR_SLEEP BIT(0)
0032
0033 static struct ingenic_cgu *cgu;
0034
0035 static const s8 pll_od_encoding[4] = {
0036 0x0, 0x1, -1, 0x3,
0037 };
0038
0039 static const u8 jz4725b_cgu_cpccr_div_table[] = {
0040 1, 2, 3, 4, 6, 8,
0041 };
0042
0043 static const u8 jz4725b_cgu_pll_half_div_table[] = {
0044 2, 1,
0045 };
0046
0047 static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = {
0048
0049
0050
0051 [JZ4725B_CLK_EXT] = { "ext", CGU_CLK_EXT },
0052 [JZ4725B_CLK_OSC32K] = { "osc32k", CGU_CLK_EXT },
0053
0054 [JZ4725B_CLK_PLL] = {
0055 "pll", CGU_CLK_PLL,
0056 .parents = { JZ4725B_CLK_EXT, -1, -1, -1 },
0057 .pll = {
0058 .reg = CGU_REG_CPPCR,
0059 .rate_multiplier = 1,
0060 .m_shift = 23,
0061 .m_bits = 9,
0062 .m_offset = 2,
0063 .n_shift = 18,
0064 .n_bits = 5,
0065 .n_offset = 2,
0066 .od_shift = 16,
0067 .od_bits = 2,
0068 .od_max = 4,
0069 .od_encoding = pll_od_encoding,
0070 .stable_bit = 10,
0071 .bypass_reg = CGU_REG_CPPCR,
0072 .bypass_bit = 9,
0073 .enable_bit = 8,
0074 },
0075 },
0076
0077
0078
0079 [JZ4725B_CLK_PLL_HALF] = {
0080 "pll half", CGU_CLK_DIV,
0081 .parents = { JZ4725B_CLK_PLL, -1, -1, -1 },
0082 .div = {
0083 CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1, 0,
0084 jz4725b_cgu_pll_half_div_table,
0085 },
0086 },
0087
0088 [JZ4725B_CLK_CCLK] = {
0089 "cclk", CGU_CLK_DIV,
0090
0091
0092
0093
0094 .flags = CLK_IS_CRITICAL,
0095 .parents = { JZ4725B_CLK_PLL, -1, -1, -1 },
0096 .div = {
0097 CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, 0,
0098 jz4725b_cgu_cpccr_div_table,
0099 },
0100 },
0101
0102 [JZ4725B_CLK_HCLK] = {
0103 "hclk", CGU_CLK_DIV,
0104 .parents = { JZ4725B_CLK_PLL, -1, -1, -1 },
0105 .div = {
0106 CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, 0,
0107 jz4725b_cgu_cpccr_div_table,
0108 },
0109 },
0110
0111 [JZ4725B_CLK_PCLK] = {
0112 "pclk", CGU_CLK_DIV,
0113 .parents = { JZ4725B_CLK_PLL, -1, -1, -1 },
0114 .div = {
0115 CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, 0,
0116 jz4725b_cgu_cpccr_div_table,
0117 },
0118 },
0119
0120 [JZ4725B_CLK_MCLK] = {
0121 "mclk", CGU_CLK_DIV,
0122
0123
0124
0125
0126 .flags = CLK_IS_CRITICAL,
0127 .parents = { JZ4725B_CLK_PLL, -1, -1, -1 },
0128 .div = {
0129 CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, 0,
0130 jz4725b_cgu_cpccr_div_table,
0131 },
0132 },
0133
0134 [JZ4725B_CLK_IPU] = {
0135 "ipu", CGU_CLK_DIV | CGU_CLK_GATE,
0136 .parents = { JZ4725B_CLK_PLL, -1, -1, -1 },
0137 .div = {
0138 CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1, 0,
0139 jz4725b_cgu_cpccr_div_table,
0140 },
0141 .gate = { CGU_REG_CLKGR, 13 },
0142 },
0143
0144 [JZ4725B_CLK_LCD] = {
0145 "lcd", CGU_CLK_DIV | CGU_CLK_GATE,
0146 .parents = { JZ4725B_CLK_PLL_HALF, -1, -1, -1 },
0147 .div = { CGU_REG_LPCDR, 0, 1, 11, -1, -1, -1 },
0148 .gate = { CGU_REG_CLKGR, 9 },
0149 },
0150
0151 [JZ4725B_CLK_I2S] = {
0152 "i2s", CGU_CLK_MUX | CGU_CLK_DIV,
0153 .parents = { JZ4725B_CLK_EXT, JZ4725B_CLK_PLL_HALF, -1, -1 },
0154 .mux = { CGU_REG_CPCCR, 31, 1 },
0155 .div = { CGU_REG_I2SCDR, 0, 1, 9, -1, -1, -1 },
0156 },
0157
0158 [JZ4725B_CLK_SPI] = {
0159 "spi", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
0160 .parents = { JZ4725B_CLK_EXT, JZ4725B_CLK_PLL, -1, -1 },
0161 .mux = { CGU_REG_SSICDR, 31, 1 },
0162 .div = { CGU_REG_SSICDR, 0, 1, 4, -1, -1, -1 },
0163 .gate = { CGU_REG_CLKGR, 4 },
0164 },
0165
0166 [JZ4725B_CLK_MMC_MUX] = {
0167 "mmc_mux", CGU_CLK_DIV,
0168 .parents = { JZ4725B_CLK_PLL_HALF, -1, -1, -1 },
0169 .div = { CGU_REG_MSCCDR, 0, 1, 5, -1, -1, -1 },
0170 },
0171
0172 [JZ4725B_CLK_UDC] = {
0173 "udc", CGU_CLK_MUX | CGU_CLK_DIV,
0174 .parents = { JZ4725B_CLK_EXT, JZ4725B_CLK_PLL_HALF, -1, -1 },
0175 .mux = { CGU_REG_CPCCR, 29, 1 },
0176 .div = { CGU_REG_CPCCR, 23, 1, 6, -1, -1, -1 },
0177 },
0178
0179
0180
0181 [JZ4725B_CLK_UART] = {
0182 "uart", CGU_CLK_GATE,
0183 .parents = { JZ4725B_CLK_EXT, -1, -1, -1 },
0184 .gate = { CGU_REG_CLKGR, 0 },
0185 },
0186
0187 [JZ4725B_CLK_DMA] = {
0188 "dma", CGU_CLK_GATE,
0189 .parents = { JZ4725B_CLK_PCLK, -1, -1, -1 },
0190 .gate = { CGU_REG_CLKGR, 12 },
0191 },
0192
0193 [JZ4725B_CLK_ADC] = {
0194 "adc", CGU_CLK_GATE,
0195 .parents = { JZ4725B_CLK_EXT, -1, -1, -1 },
0196 .gate = { CGU_REG_CLKGR, 7 },
0197 },
0198
0199 [JZ4725B_CLK_I2C] = {
0200 "i2c", CGU_CLK_GATE,
0201 .parents = { JZ4725B_CLK_EXT, -1, -1, -1 },
0202 .gate = { CGU_REG_CLKGR, 3 },
0203 },
0204
0205 [JZ4725B_CLK_AIC] = {
0206 "aic", CGU_CLK_GATE,
0207 .parents = { JZ4725B_CLK_EXT, -1, -1, -1 },
0208 .gate = { CGU_REG_CLKGR, 5 },
0209 },
0210
0211 [JZ4725B_CLK_MMC0] = {
0212 "mmc0", CGU_CLK_GATE,
0213 .parents = { JZ4725B_CLK_MMC_MUX, -1, -1, -1 },
0214 .gate = { CGU_REG_CLKGR, 6 },
0215 },
0216
0217 [JZ4725B_CLK_MMC1] = {
0218 "mmc1", CGU_CLK_GATE,
0219 .parents = { JZ4725B_CLK_MMC_MUX, -1, -1, -1 },
0220 .gate = { CGU_REG_CLKGR, 16 },
0221 },
0222
0223 [JZ4725B_CLK_BCH] = {
0224 "bch", CGU_CLK_GATE,
0225 .parents = { JZ4725B_CLK_MCLK, -1, -1, -1 },
0226 .gate = { CGU_REG_CLKGR, 11 },
0227 },
0228
0229 [JZ4725B_CLK_TCU] = {
0230 "tcu", CGU_CLK_GATE,
0231 .parents = { JZ4725B_CLK_EXT, -1, -1, -1 },
0232 .gate = { CGU_REG_CLKGR, 1 },
0233 },
0234
0235 [JZ4725B_CLK_EXT512] = {
0236 "ext/512", CGU_CLK_FIXDIV,
0237 .parents = { JZ4725B_CLK_EXT },
0238
0239
0240 .fixdiv = { 256 },
0241 },
0242
0243 [JZ4725B_CLK_RTC] = {
0244 "rtc", CGU_CLK_MUX,
0245 .parents = { JZ4725B_CLK_EXT512, JZ4725B_CLK_OSC32K, -1, -1 },
0246 .mux = { CGU_REG_OPCR, 2, 1},
0247 },
0248
0249 [JZ4725B_CLK_UDC_PHY] = {
0250 "udc_phy", CGU_CLK_GATE,
0251 .parents = { JZ4725B_CLK_EXT, -1, -1, -1 },
0252 .gate = { CGU_REG_OPCR, 6, true },
0253 },
0254 };
0255
0256 static void __init jz4725b_cgu_init(struct device_node *np)
0257 {
0258 int retval;
0259
0260 cgu = ingenic_cgu_new(jz4725b_cgu_clocks,
0261 ARRAY_SIZE(jz4725b_cgu_clocks), np);
0262 if (!cgu) {
0263 pr_err("%s: failed to initialise CGU\n", __func__);
0264 return;
0265 }
0266
0267 retval = ingenic_cgu_register_clocks(cgu);
0268 if (retval)
0269 pr_err("%s: failed to register CGU Clocks\n", __func__);
0270
0271 ingenic_cgu_register_syscore_ops(cgu);
0272 }
0273 CLK_OF_DECLARE_DRIVER(jz4725b_cgu, "ingenic,jz4725b-cgu", jz4725b_cgu_init);