Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | /* |
| 3 | * X1000 SoC CGU driver |
周琰杰 (Zhou Yanjie) | 440d7a6f | 2020-05-28 11:15:49 +0800 | [diff] [blame] | 4 | * Copyright (c) 2019 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com> |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 5 | */ |
| 6 | |
| 7 | #include <linux/clk-provider.h> |
| 8 | #include <linux/delay.h> |
周琰杰 (Zhou Yanjie) | 440d7a6f | 2020-05-28 11:15:49 +0800 | [diff] [blame] | 9 | #include <linux/io.h> |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 10 | #include <linux/of.h> |
Aidan MacDonald | 662e8ed | 2022-10-26 20:43:44 +0100 | [diff] [blame] | 11 | #include <linux/rational.h> |
周琰杰 (Zhou Yanjie) | 9d9cc58 | 2020-05-28 11:15:44 +0800 | [diff] [blame] | 12 | |
Paul Cercueil | c4a11bf | 2021-10-16 14:33:21 +0100 | [diff] [blame] | 13 | #include <dt-bindings/clock/ingenic,x1000-cgu.h> |
周琰杰 (Zhou Yanjie) | 9d9cc58 | 2020-05-28 11:15:44 +0800 | [diff] [blame] | 14 | |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 15 | #include "cgu.h" |
| 16 | #include "pm.h" |
| 17 | |
| 18 | /* CGU register offsets */ |
| 19 | #define CGU_REG_CPCCR 0x00 |
| 20 | #define CGU_REG_APLL 0x10 |
| 21 | #define CGU_REG_MPLL 0x14 |
| 22 | #define CGU_REG_CLKGR 0x20 |
| 23 | #define CGU_REG_OPCR 0x24 |
| 24 | #define CGU_REG_DDRCDR 0x2c |
周琰杰 (Zhou Yanjie) | 440d7a6f | 2020-05-28 11:15:49 +0800 | [diff] [blame] | 25 | #define CGU_REG_USBPCR 0x3c |
| 26 | #define CGU_REG_USBPCR1 0x48 |
| 27 | #define CGU_REG_USBCDR 0x50 |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 28 | #define CGU_REG_MACCDR 0x54 |
| 29 | #define CGU_REG_I2SCDR 0x60 |
| 30 | #define CGU_REG_LPCDR 0x64 |
| 31 | #define CGU_REG_MSC0CDR 0x68 |
| 32 | #define CGU_REG_I2SCDR1 0x70 |
| 33 | #define CGU_REG_SSICDR 0x74 |
| 34 | #define CGU_REG_CIMCDR 0x7c |
| 35 | #define CGU_REG_PCMCDR 0x84 |
| 36 | #define CGU_REG_MSC1CDR 0xa4 |
| 37 | #define CGU_REG_CMP_INTR 0xb0 |
| 38 | #define CGU_REG_CMP_INTRE 0xb4 |
| 39 | #define CGU_REG_DRCG 0xd0 |
| 40 | #define CGU_REG_CPCSR 0xd4 |
| 41 | #define CGU_REG_PCMCDR1 0xe0 |
| 42 | #define CGU_REG_MACPHYC 0xe8 |
| 43 | |
| 44 | /* bits within the OPCR register */ |
| 45 | #define OPCR_SPENDN0 BIT(7) |
| 46 | #define OPCR_SPENDN1 BIT(6) |
| 47 | |
周琰杰 (Zhou Yanjie) | 440d7a6f | 2020-05-28 11:15:49 +0800 | [diff] [blame] | 48 | /* bits within the USBPCR register */ |
| 49 | #define USBPCR_SIDDQ BIT(21) |
| 50 | #define USBPCR_OTG_DISABLE BIT(20) |
| 51 | |
周琰杰 (Zhou Yanjie) | 810797c | 2020-07-01 00:38:52 +0800 | [diff] [blame] | 52 | /* bits within the USBPCR1 register */ |
| 53 | #define USBPCR1_REFCLKSEL_SHIFT 26 |
| 54 | #define USBPCR1_REFCLKSEL_MASK (0x3 << USBPCR1_REFCLKSEL_SHIFT) |
| 55 | #define USBPCR1_REFCLKSEL_CORE (0x2 << USBPCR1_REFCLKSEL_SHIFT) |
| 56 | #define USBPCR1_REFCLKDIV_SHIFT 24 |
| 57 | #define USBPCR1_REFCLKDIV_MASK (0x3 << USBPCR1_REFCLKDIV_SHIFT) |
| 58 | #define USBPCR1_REFCLKDIV_48 (0x2 << USBPCR1_REFCLKDIV_SHIFT) |
| 59 | #define USBPCR1_REFCLKDIV_24 (0x1 << USBPCR1_REFCLKDIV_SHIFT) |
| 60 | #define USBPCR1_REFCLKDIV_12 (0x0 << USBPCR1_REFCLKDIV_SHIFT) |
| 61 | |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 62 | static struct ingenic_cgu *cgu; |
| 63 | |
周琰杰 (Zhou Yanjie) | 810797c | 2020-07-01 00:38:52 +0800 | [diff] [blame] | 64 | static unsigned long x1000_otg_phy_recalc_rate(struct clk_hw *hw, |
| 65 | unsigned long parent_rate) |
| 66 | { |
| 67 | u32 usbpcr1; |
| 68 | unsigned refclk_div; |
| 69 | |
| 70 | usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1); |
| 71 | refclk_div = usbpcr1 & USBPCR1_REFCLKDIV_MASK; |
| 72 | |
| 73 | switch (refclk_div) { |
| 74 | case USBPCR1_REFCLKDIV_12: |
| 75 | return 12000000; |
| 76 | |
| 77 | case USBPCR1_REFCLKDIV_24: |
| 78 | return 24000000; |
| 79 | |
| 80 | case USBPCR1_REFCLKDIV_48: |
| 81 | return 48000000; |
| 82 | } |
| 83 | |
| 84 | return parent_rate; |
| 85 | } |
| 86 | |
| 87 | static long x1000_otg_phy_round_rate(struct clk_hw *hw, unsigned long req_rate, |
| 88 | unsigned long *parent_rate) |
| 89 | { |
| 90 | if (req_rate < 18000000) |
| 91 | return 12000000; |
| 92 | |
| 93 | if (req_rate < 36000000) |
| 94 | return 24000000; |
| 95 | |
| 96 | return 48000000; |
| 97 | } |
| 98 | |
| 99 | static int x1000_otg_phy_set_rate(struct clk_hw *hw, unsigned long req_rate, |
| 100 | unsigned long parent_rate) |
| 101 | { |
| 102 | unsigned long flags; |
| 103 | u32 usbpcr1, div_bits; |
| 104 | |
| 105 | switch (req_rate) { |
| 106 | case 12000000: |
| 107 | div_bits = USBPCR1_REFCLKDIV_12; |
| 108 | break; |
| 109 | |
| 110 | case 24000000: |
| 111 | div_bits = USBPCR1_REFCLKDIV_24; |
| 112 | break; |
| 113 | |
| 114 | case 48000000: |
| 115 | div_bits = USBPCR1_REFCLKDIV_48; |
| 116 | break; |
| 117 | |
| 118 | default: |
| 119 | return -EINVAL; |
| 120 | } |
| 121 | |
| 122 | spin_lock_irqsave(&cgu->lock, flags); |
| 123 | |
| 124 | usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1); |
| 125 | usbpcr1 &= ~USBPCR1_REFCLKDIV_MASK; |
| 126 | usbpcr1 |= div_bits; |
| 127 | writel(usbpcr1, cgu->base + CGU_REG_USBPCR1); |
| 128 | |
| 129 | spin_unlock_irqrestore(&cgu->lock, flags); |
| 130 | return 0; |
| 131 | } |
| 132 | |
周琰杰 (Zhou Yanjie) | 440d7a6f | 2020-05-28 11:15:49 +0800 | [diff] [blame] | 133 | static int x1000_usb_phy_enable(struct clk_hw *hw) |
| 134 | { |
| 135 | void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR; |
| 136 | void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR; |
| 137 | |
| 138 | writel(readl(reg_opcr) | OPCR_SPENDN0, reg_opcr); |
| 139 | writel(readl(reg_usbpcr) & ~USBPCR_OTG_DISABLE & ~USBPCR_SIDDQ, reg_usbpcr); |
| 140 | return 0; |
| 141 | } |
| 142 | |
| 143 | static void x1000_usb_phy_disable(struct clk_hw *hw) |
| 144 | { |
| 145 | void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR; |
| 146 | void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR; |
| 147 | |
| 148 | writel(readl(reg_opcr) & ~OPCR_SPENDN0, reg_opcr); |
| 149 | writel(readl(reg_usbpcr) | USBPCR_OTG_DISABLE | USBPCR_SIDDQ, reg_usbpcr); |
| 150 | } |
| 151 | |
| 152 | static int x1000_usb_phy_is_enabled(struct clk_hw *hw) |
| 153 | { |
| 154 | void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR; |
| 155 | void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR; |
| 156 | |
| 157 | return (readl(reg_opcr) & OPCR_SPENDN0) && |
| 158 | !(readl(reg_usbpcr) & USBPCR_SIDDQ) && |
| 159 | !(readl(reg_usbpcr) & USBPCR_OTG_DISABLE); |
| 160 | } |
| 161 | |
| 162 | static const struct clk_ops x1000_otg_phy_ops = { |
周琰杰 (Zhou Yanjie) | 810797c | 2020-07-01 00:38:52 +0800 | [diff] [blame] | 163 | .recalc_rate = x1000_otg_phy_recalc_rate, |
| 164 | .round_rate = x1000_otg_phy_round_rate, |
| 165 | .set_rate = x1000_otg_phy_set_rate, |
| 166 | |
周琰杰 (Zhou Yanjie) | 440d7a6f | 2020-05-28 11:15:49 +0800 | [diff] [blame] | 167 | .enable = x1000_usb_phy_enable, |
| 168 | .disable = x1000_usb_phy_disable, |
| 169 | .is_enabled = x1000_usb_phy_is_enabled, |
| 170 | }; |
| 171 | |
Aidan MacDonald | 662e8ed | 2022-10-26 20:43:44 +0100 | [diff] [blame] | 172 | static void |
| 173 | x1000_i2spll_calc_m_n_od(const struct ingenic_cgu_pll_info *pll_info, |
| 174 | unsigned long rate, unsigned long parent_rate, |
| 175 | unsigned int *pm, unsigned int *pn, unsigned int *pod) |
| 176 | { |
| 177 | const unsigned long m_max = GENMASK(pll_info->m_bits - 1, 0); |
| 178 | const unsigned long n_max = GENMASK(pll_info->n_bits - 1, 0); |
| 179 | unsigned long m, n; |
| 180 | |
| 181 | rational_best_approximation(rate, parent_rate, m_max, n_max, &m, &n); |
| 182 | |
| 183 | /* n should not be less than 2*m */ |
| 184 | if (n < 2 * m) |
| 185 | n = 2 * m; |
| 186 | |
| 187 | *pm = m; |
| 188 | *pn = n; |
| 189 | *pod = 1; |
| 190 | } |
| 191 | |
| 192 | static void |
| 193 | x1000_i2spll_set_rate_hook(const struct ingenic_cgu_pll_info *pll_info, |
| 194 | unsigned long rate, unsigned long parent_rate) |
| 195 | { |
| 196 | /* |
| 197 | * Writing 0 causes I2SCDR1.I2SDIV_D to be automatically recalculated |
| 198 | * based on the current value of I2SCDR.I2SDIV_N, which is needed for |
| 199 | * the divider to function correctly. |
| 200 | */ |
| 201 | writel(0, cgu->base + CGU_REG_I2SCDR1); |
| 202 | } |
| 203 | |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 204 | static const s8 pll_od_encoding[8] = { |
| 205 | 0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3, |
| 206 | }; |
| 207 | |
| 208 | static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = { |
| 209 | |
| 210 | /* External clocks */ |
| 211 | |
| 212 | [X1000_CLK_EXCLK] = { "ext", CGU_CLK_EXT }, |
| 213 | [X1000_CLK_RTCLK] = { "rtc", CGU_CLK_EXT }, |
| 214 | |
| 215 | /* PLLs */ |
| 216 | |
| 217 | [X1000_CLK_APLL] = { |
| 218 | "apll", CGU_CLK_PLL, |
Aidan MacDonald | 8fe873d | 2022-10-26 20:43:45 +0100 | [diff] [blame] | 219 | .parents = { X1000_CLK_EXCLK }, |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 220 | .pll = { |
| 221 | .reg = CGU_REG_APLL, |
周琰杰 (Zhou Yanjie) | 9d9cc58 | 2020-05-28 11:15:44 +0800 | [diff] [blame] | 222 | .rate_multiplier = 1, |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 223 | .m_shift = 24, |
| 224 | .m_bits = 7, |
| 225 | .m_offset = 1, |
| 226 | .n_shift = 18, |
| 227 | .n_bits = 5, |
| 228 | .n_offset = 1, |
| 229 | .od_shift = 16, |
| 230 | .od_bits = 2, |
| 231 | .od_max = 8, |
| 232 | .od_encoding = pll_od_encoding, |
周琰杰 (Zhou Yanjie) | 9d9cc58 | 2020-05-28 11:15:44 +0800 | [diff] [blame] | 233 | .bypass_reg = CGU_REG_APLL, |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 234 | .bypass_bit = 9, |
| 235 | .enable_bit = 8, |
| 236 | .stable_bit = 10, |
| 237 | }, |
| 238 | }, |
| 239 | |
| 240 | [X1000_CLK_MPLL] = { |
| 241 | "mpll", CGU_CLK_PLL, |
Aidan MacDonald | 8fe873d | 2022-10-26 20:43:45 +0100 | [diff] [blame] | 242 | .parents = { X1000_CLK_EXCLK }, |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 243 | .pll = { |
| 244 | .reg = CGU_REG_MPLL, |
周琰杰 (Zhou Yanjie) | 9d9cc58 | 2020-05-28 11:15:44 +0800 | [diff] [blame] | 245 | .rate_multiplier = 1, |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 246 | .m_shift = 24, |
| 247 | .m_bits = 7, |
| 248 | .m_offset = 1, |
| 249 | .n_shift = 18, |
| 250 | .n_bits = 5, |
| 251 | .n_offset = 1, |
| 252 | .od_shift = 16, |
| 253 | .od_bits = 2, |
| 254 | .od_max = 8, |
| 255 | .od_encoding = pll_od_encoding, |
周琰杰 (Zhou Yanjie) | 9d9cc58 | 2020-05-28 11:15:44 +0800 | [diff] [blame] | 256 | .bypass_reg = CGU_REG_MPLL, |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 257 | .bypass_bit = 6, |
| 258 | .enable_bit = 7, |
| 259 | .stable_bit = 0, |
| 260 | }, |
| 261 | }, |
| 262 | |
周琰杰 (Zhou Yanjie) | 440d7a6f | 2020-05-28 11:15:49 +0800 | [diff] [blame] | 263 | /* Custom (SoC-specific) OTG PHY */ |
| 264 | |
| 265 | [X1000_CLK_OTGPHY] = { |
| 266 | "otg_phy", CGU_CLK_CUSTOM, |
| 267 | .parents = { -1, -1, X1000_CLK_EXCLK, -1 }, |
| 268 | .custom = { &x1000_otg_phy_ops }, |
| 269 | }, |
| 270 | |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 271 | /* Muxes & dividers */ |
| 272 | |
| 273 | [X1000_CLK_SCLKA] = { |
| 274 | "sclk_a", CGU_CLK_MUX, |
| 275 | .parents = { -1, X1000_CLK_EXCLK, X1000_CLK_APLL, -1 }, |
| 276 | .mux = { CGU_REG_CPCCR, 30, 2 }, |
| 277 | }, |
| 278 | |
| 279 | [X1000_CLK_CPUMUX] = { |
| 280 | "cpu_mux", CGU_CLK_MUX, |
| 281 | .parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 }, |
| 282 | .mux = { CGU_REG_CPCCR, 28, 2 }, |
| 283 | }, |
| 284 | |
| 285 | [X1000_CLK_CPU] = { |
周琰杰 (Zhou Yanjie) | 440d7a6f | 2020-05-28 11:15:49 +0800 | [diff] [blame] | 286 | "cpu", CGU_CLK_DIV | CGU_CLK_GATE, |
Aidan MacDonald | ca54d06 | 2022-04-28 17:44:53 +0100 | [diff] [blame] | 287 | /* |
| 288 | * Disabling the CPU clock or any parent clocks will hang the |
| 289 | * system; mark it critical. |
| 290 | */ |
| 291 | .flags = CLK_IS_CRITICAL, |
Aidan MacDonald | 8fe873d | 2022-10-26 20:43:45 +0100 | [diff] [blame] | 292 | .parents = { X1000_CLK_CPUMUX }, |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 293 | .div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1 }, |
周琰杰 (Zhou Yanjie) | 440d7a6f | 2020-05-28 11:15:49 +0800 | [diff] [blame] | 294 | .gate = { CGU_REG_CLKGR, 30 }, |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 295 | }, |
| 296 | |
| 297 | [X1000_CLK_L2CACHE] = { |
| 298 | "l2cache", CGU_CLK_DIV, |
Aidan MacDonald | ca54d06 | 2022-04-28 17:44:53 +0100 | [diff] [blame] | 299 | /* |
| 300 | * The L2 cache clock is critical if caches are enabled and |
| 301 | * disabling it or any parent clocks will hang the system. |
| 302 | */ |
| 303 | .flags = CLK_IS_CRITICAL, |
Aidan MacDonald | 8fe873d | 2022-10-26 20:43:45 +0100 | [diff] [blame] | 304 | .parents = { X1000_CLK_CPUMUX }, |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 305 | .div = { CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1 }, |
| 306 | }, |
| 307 | |
| 308 | [X1000_CLK_AHB0] = { |
| 309 | "ahb0", CGU_CLK_MUX | CGU_CLK_DIV, |
| 310 | .parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 }, |
| 311 | .mux = { CGU_REG_CPCCR, 26, 2 }, |
| 312 | .div = { CGU_REG_CPCCR, 8, 1, 4, 21, -1, -1 }, |
| 313 | }, |
| 314 | |
| 315 | [X1000_CLK_AHB2PMUX] = { |
| 316 | "ahb2_apb_mux", CGU_CLK_MUX, |
| 317 | .parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 }, |
| 318 | .mux = { CGU_REG_CPCCR, 24, 2 }, |
| 319 | }, |
| 320 | |
| 321 | [X1000_CLK_AHB2] = { |
| 322 | "ahb2", CGU_CLK_DIV, |
Aidan MacDonald | 8fe873d | 2022-10-26 20:43:45 +0100 | [diff] [blame] | 323 | .parents = { X1000_CLK_AHB2PMUX }, |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 324 | .div = { CGU_REG_CPCCR, 12, 1, 4, 20, -1, -1 }, |
| 325 | }, |
| 326 | |
| 327 | [X1000_CLK_PCLK] = { |
周琰杰 (Zhou Yanjie) | 440d7a6f | 2020-05-28 11:15:49 +0800 | [diff] [blame] | 328 | "pclk", CGU_CLK_DIV | CGU_CLK_GATE, |
Aidan MacDonald | 8fe873d | 2022-10-26 20:43:45 +0100 | [diff] [blame] | 329 | .parents = { X1000_CLK_AHB2PMUX }, |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 330 | .div = { CGU_REG_CPCCR, 16, 1, 4, 20, -1, -1 }, |
周琰杰 (Zhou Yanjie) | 440d7a6f | 2020-05-28 11:15:49 +0800 | [diff] [blame] | 331 | .gate = { CGU_REG_CLKGR, 28 }, |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 332 | }, |
| 333 | |
| 334 | [X1000_CLK_DDR] = { |
| 335 | "ddr", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE, |
Aidan MacDonald | ca54d06 | 2022-04-28 17:44:53 +0100 | [diff] [blame] | 336 | /* |
| 337 | * Disabling DDR clock or its parents will render DRAM |
| 338 | * inaccessible; mark it critical. |
| 339 | */ |
| 340 | .flags = CLK_IS_CRITICAL, |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 341 | .parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 }, |
| 342 | .mux = { CGU_REG_DDRCDR, 30, 2 }, |
| 343 | .div = { CGU_REG_DDRCDR, 0, 1, 4, 29, 28, 27 }, |
| 344 | .gate = { CGU_REG_CLKGR, 31 }, |
| 345 | }, |
| 346 | |
| 347 | [X1000_CLK_MAC] = { |
| 348 | "mac", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE, |
周琰杰 (Zhou Yanjie) | 440d7a6f | 2020-05-28 11:15:49 +0800 | [diff] [blame] | 349 | .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL }, |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 350 | .mux = { CGU_REG_MACCDR, 31, 1 }, |
| 351 | .div = { CGU_REG_MACCDR, 0, 1, 8, 29, 28, 27 }, |
| 352 | .gate = { CGU_REG_CLKGR, 25 }, |
| 353 | }, |
| 354 | |
Aidan MacDonald | 662e8ed | 2022-10-26 20:43:44 +0100 | [diff] [blame] | 355 | [X1000_CLK_I2SPLLMUX] = { |
| 356 | "i2s_pll_mux", CGU_CLK_MUX, |
| 357 | .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL }, |
| 358 | .mux = { CGU_REG_I2SCDR, 31, 1 }, |
| 359 | }, |
| 360 | |
| 361 | [X1000_CLK_I2SPLL] = { |
| 362 | "i2s_pll", CGU_CLK_PLL, |
| 363 | .parents = { X1000_CLK_I2SPLLMUX }, |
| 364 | .pll = { |
| 365 | .reg = CGU_REG_I2SCDR, |
| 366 | .rate_multiplier = 1, |
| 367 | .m_shift = 13, |
| 368 | .m_bits = 9, |
| 369 | .n_shift = 0, |
| 370 | .n_bits = 13, |
| 371 | .calc_m_n_od = x1000_i2spll_calc_m_n_od, |
| 372 | .set_rate_hook = x1000_i2spll_set_rate_hook, |
| 373 | }, |
| 374 | }, |
| 375 | |
| 376 | [X1000_CLK_I2S] = { |
| 377 | "i2s", CGU_CLK_MUX, |
| 378 | .parents = { X1000_CLK_EXCLK, -1, -1, X1000_CLK_I2SPLL }, |
| 379 | /* |
| 380 | * NOTE: the mux is at bit 30; bit 29 enables the M/N divider. |
| 381 | * Therefore, the divider is disabled when EXCLK is selected. |
| 382 | */ |
| 383 | .mux = { CGU_REG_I2SCDR, 29, 2 }, |
| 384 | }, |
| 385 | |
周琰杰 (Zhou Yanjie) | 440d7a6f | 2020-05-28 11:15:49 +0800 | [diff] [blame] | 386 | [X1000_CLK_LCD] = { |
| 387 | "lcd", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE, |
| 388 | .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL }, |
| 389 | .mux = { CGU_REG_LPCDR, 31, 1 }, |
| 390 | .div = { CGU_REG_LPCDR, 0, 1, 8, 28, 27, 26 }, |
| 391 | .gate = { CGU_REG_CLKGR, 23 }, |
| 392 | }, |
| 393 | |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 394 | [X1000_CLK_MSCMUX] = { |
| 395 | "msc_mux", CGU_CLK_MUX, |
Aidan MacDonald | 8fe873d | 2022-10-26 20:43:45 +0100 | [diff] [blame] | 396 | .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL }, |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 397 | .mux = { CGU_REG_MSC0CDR, 31, 1 }, |
| 398 | }, |
| 399 | |
| 400 | [X1000_CLK_MSC0] = { |
| 401 | "msc0", CGU_CLK_DIV | CGU_CLK_GATE, |
Aidan MacDonald | 8fe873d | 2022-10-26 20:43:45 +0100 | [diff] [blame] | 402 | .parents = { X1000_CLK_MSCMUX }, |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 403 | .div = { CGU_REG_MSC0CDR, 0, 2, 8, 29, 28, 27 }, |
| 404 | .gate = { CGU_REG_CLKGR, 4 }, |
| 405 | }, |
| 406 | |
| 407 | [X1000_CLK_MSC1] = { |
| 408 | "msc1", CGU_CLK_DIV | CGU_CLK_GATE, |
| 409 | .parents = { X1000_CLK_MSCMUX, -1, -1, -1 }, |
| 410 | .div = { CGU_REG_MSC1CDR, 0, 2, 8, 29, 28, 27 }, |
| 411 | .gate = { CGU_REG_CLKGR, 5 }, |
| 412 | }, |
| 413 | |
周琰杰 (Zhou Yanjie) | 440d7a6f | 2020-05-28 11:15:49 +0800 | [diff] [blame] | 414 | [X1000_CLK_OTG] = { |
| 415 | "otg", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, |
Aidan MacDonald | 8fe873d | 2022-10-26 20:43:45 +0100 | [diff] [blame] | 416 | .parents = { X1000_CLK_EXCLK, -1, X1000_CLK_APLL, X1000_CLK_MPLL }, |
周琰杰 (Zhou Yanjie) | 440d7a6f | 2020-05-28 11:15:49 +0800 | [diff] [blame] | 417 | .mux = { CGU_REG_USBCDR, 30, 2 }, |
| 418 | .div = { CGU_REG_USBCDR, 0, 1, 8, 29, 28, 27 }, |
| 419 | .gate = { CGU_REG_CLKGR, 3 }, |
| 420 | }, |
| 421 | |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 422 | [X1000_CLK_SSIPLL] = { |
| 423 | "ssi_pll", CGU_CLK_MUX | CGU_CLK_DIV, |
Aidan MacDonald | 8fe873d | 2022-10-26 20:43:45 +0100 | [diff] [blame] | 424 | .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL }, |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 425 | .mux = { CGU_REG_SSICDR, 31, 1 }, |
| 426 | .div = { CGU_REG_SSICDR, 0, 1, 8, 29, 28, 27 }, |
| 427 | }, |
| 428 | |
周琰杰 (Zhou Yanjie) | 440d7a6f | 2020-05-28 11:15:49 +0800 | [diff] [blame] | 429 | [X1000_CLK_SSIPLL_DIV2] = { |
| 430 | "ssi_pll_div2", CGU_CLK_FIXDIV, |
| 431 | .parents = { X1000_CLK_SSIPLL }, |
| 432 | .fixdiv = { 2 }, |
| 433 | }, |
| 434 | |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 435 | [X1000_CLK_SSIMUX] = { |
| 436 | "ssi_mux", CGU_CLK_MUX, |
Aidan MacDonald | 8fe873d | 2022-10-26 20:43:45 +0100 | [diff] [blame] | 437 | .parents = { X1000_CLK_EXCLK, X1000_CLK_SSIPLL_DIV2 }, |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 438 | .mux = { CGU_REG_SSICDR, 30, 1 }, |
| 439 | }, |
| 440 | |
周琰杰 (Zhou Yanjie) | 82df5b7 | 2020-07-25 13:11:36 +0800 | [diff] [blame] | 441 | [X1000_CLK_EXCLK_DIV512] = { |
| 442 | "exclk_div512", CGU_CLK_FIXDIV, |
| 443 | .parents = { X1000_CLK_EXCLK }, |
| 444 | .fixdiv = { 512 }, |
| 445 | }, |
| 446 | |
| 447 | [X1000_CLK_RTC] = { |
| 448 | "rtc_ercs", CGU_CLK_MUX | CGU_CLK_GATE, |
| 449 | .parents = { X1000_CLK_EXCLK_DIV512, X1000_CLK_RTCLK }, |
| 450 | .mux = { CGU_REG_OPCR, 2, 1}, |
| 451 | .gate = { CGU_REG_CLKGR, 27 }, |
| 452 | }, |
| 453 | |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 454 | /* Gate-only clocks */ |
| 455 | |
周琰杰 (Zhou Yanjie) | 440d7a6f | 2020-05-28 11:15:49 +0800 | [diff] [blame] | 456 | [X1000_CLK_EMC] = { |
| 457 | "emc", CGU_CLK_GATE, |
Aidan MacDonald | 8fe873d | 2022-10-26 20:43:45 +0100 | [diff] [blame] | 458 | .parents = { X1000_CLK_AHB2 }, |
周琰杰 (Zhou Yanjie) | 440d7a6f | 2020-05-28 11:15:49 +0800 | [diff] [blame] | 459 | .gate = { CGU_REG_CLKGR, 0 }, |
| 460 | }, |
| 461 | |
| 462 | [X1000_CLK_EFUSE] = { |
| 463 | "efuse", CGU_CLK_GATE, |
Aidan MacDonald | 8fe873d | 2022-10-26 20:43:45 +0100 | [diff] [blame] | 464 | .parents = { X1000_CLK_AHB2 }, |
周琰杰 (Zhou Yanjie) | 440d7a6f | 2020-05-28 11:15:49 +0800 | [diff] [blame] | 465 | .gate = { CGU_REG_CLKGR, 1 }, |
| 466 | }, |
| 467 | |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 468 | [X1000_CLK_SFC] = { |
| 469 | "sfc", CGU_CLK_GATE, |
Aidan MacDonald | 8fe873d | 2022-10-26 20:43:45 +0100 | [diff] [blame] | 470 | .parents = { X1000_CLK_SSIPLL }, |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 471 | .gate = { CGU_REG_CLKGR, 2 }, |
| 472 | }, |
| 473 | |
| 474 | [X1000_CLK_I2C0] = { |
| 475 | "i2c0", CGU_CLK_GATE, |
Aidan MacDonald | 8fe873d | 2022-10-26 20:43:45 +0100 | [diff] [blame] | 476 | .parents = { X1000_CLK_PCLK }, |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 477 | .gate = { CGU_REG_CLKGR, 7 }, |
| 478 | }, |
| 479 | |
| 480 | [X1000_CLK_I2C1] = { |
| 481 | "i2c1", CGU_CLK_GATE, |
Aidan MacDonald | 8fe873d | 2022-10-26 20:43:45 +0100 | [diff] [blame] | 482 | .parents = { X1000_CLK_PCLK }, |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 483 | .gate = { CGU_REG_CLKGR, 8 }, |
| 484 | }, |
| 485 | |
| 486 | [X1000_CLK_I2C2] = { |
| 487 | "i2c2", CGU_CLK_GATE, |
Aidan MacDonald | 8fe873d | 2022-10-26 20:43:45 +0100 | [diff] [blame] | 488 | .parents = { X1000_CLK_PCLK }, |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 489 | .gate = { CGU_REG_CLKGR, 9 }, |
| 490 | }, |
| 491 | |
Aidan MacDonald | 662e8ed | 2022-10-26 20:43:44 +0100 | [diff] [blame] | 492 | [X1000_CLK_AIC] = { |
| 493 | "aic", CGU_CLK_GATE, |
| 494 | .parents = { X1000_CLK_EXCLK }, |
| 495 | .gate = { CGU_REG_CLKGR, 11 }, |
| 496 | }, |
| 497 | |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 498 | [X1000_CLK_UART0] = { |
| 499 | "uart0", CGU_CLK_GATE, |
Aidan MacDonald | 8fe873d | 2022-10-26 20:43:45 +0100 | [diff] [blame] | 500 | .parents = { X1000_CLK_EXCLK }, |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 501 | .gate = { CGU_REG_CLKGR, 14 }, |
| 502 | }, |
| 503 | |
| 504 | [X1000_CLK_UART1] = { |
| 505 | "uart1", CGU_CLK_GATE, |
Aidan MacDonald | 8fe873d | 2022-10-26 20:43:45 +0100 | [diff] [blame] | 506 | .parents = { X1000_CLK_EXCLK}, |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 507 | .gate = { CGU_REG_CLKGR, 15 }, |
| 508 | }, |
| 509 | |
| 510 | [X1000_CLK_UART2] = { |
| 511 | "uart2", CGU_CLK_GATE, |
Aidan MacDonald | 8fe873d | 2022-10-26 20:43:45 +0100 | [diff] [blame] | 512 | .parents = { X1000_CLK_EXCLK }, |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 513 | .gate = { CGU_REG_CLKGR, 16 }, |
| 514 | }, |
| 515 | |
周琰杰 (Zhou Yanjie) | 440d7a6f | 2020-05-28 11:15:49 +0800 | [diff] [blame] | 516 | [X1000_CLK_TCU] = { |
| 517 | "tcu", CGU_CLK_GATE, |
Aidan MacDonald | 8fe873d | 2022-10-26 20:43:45 +0100 | [diff] [blame] | 518 | .parents = { X1000_CLK_EXCLK }, |
周琰杰 (Zhou Yanjie) | 440d7a6f | 2020-05-28 11:15:49 +0800 | [diff] [blame] | 519 | .gate = { CGU_REG_CLKGR, 18 }, |
| 520 | }, |
| 521 | |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 522 | [X1000_CLK_SSI] = { |
| 523 | "ssi", CGU_CLK_GATE, |
Aidan MacDonald | 8fe873d | 2022-10-26 20:43:45 +0100 | [diff] [blame] | 524 | .parents = { X1000_CLK_SSIMUX }, |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 525 | .gate = { CGU_REG_CLKGR, 19 }, |
| 526 | }, |
| 527 | |
周琰杰 (Zhou Yanjie) | 440d7a6f | 2020-05-28 11:15:49 +0800 | [diff] [blame] | 528 | [X1000_CLK_OST] = { |
| 529 | "ost", CGU_CLK_GATE, |
Aidan MacDonald | 8fe873d | 2022-10-26 20:43:45 +0100 | [diff] [blame] | 530 | .parents = { X1000_CLK_EXCLK }, |
周琰杰 (Zhou Yanjie) | 440d7a6f | 2020-05-28 11:15:49 +0800 | [diff] [blame] | 531 | .gate = { CGU_REG_CLKGR, 20 }, |
| 532 | }, |
| 533 | |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 534 | [X1000_CLK_PDMA] = { |
| 535 | "pdma", CGU_CLK_GATE, |
Aidan MacDonald | 8fe873d | 2022-10-26 20:43:45 +0100 | [diff] [blame] | 536 | .parents = { X1000_CLK_EXCLK }, |
Zhou Yanjie | b9df399 | 2019-11-10 17:28:22 +0800 | [diff] [blame] | 537 | .gate = { CGU_REG_CLKGR, 21 }, |
| 538 | }, |
| 539 | }; |
| 540 | |
| 541 | static void __init x1000_cgu_init(struct device_node *np) |
| 542 | { |
| 543 | int retval; |
| 544 | |
| 545 | cgu = ingenic_cgu_new(x1000_cgu_clocks, |
| 546 | ARRAY_SIZE(x1000_cgu_clocks), np); |
| 547 | if (!cgu) { |
| 548 | pr_err("%s: failed to initialise CGU\n", __func__); |
| 549 | return; |
| 550 | } |
| 551 | |
| 552 | retval = ingenic_cgu_register_clocks(cgu); |
| 553 | if (retval) { |
| 554 | pr_err("%s: failed to register CGU Clocks\n", __func__); |
| 555 | return; |
| 556 | } |
| 557 | |
| 558 | ingenic_cgu_register_syscore_ops(cgu); |
| 559 | } |
周琰杰 (Zhou Yanjie) | 440d7a6f | 2020-05-28 11:15:49 +0800 | [diff] [blame] | 560 | /* |
| 561 | * CGU has some children devices, this is useful for probing children devices |
| 562 | * in the case where the device node is compatible with "simple-mfd". |
| 563 | */ |
| 564 | CLK_OF_DECLARE_DRIVER(x1000_cgu, "ingenic,x1000-cgu", x1000_cgu_init); |