1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * X1000 SoC CGU driver 4 * Copyright (c) 2019 Zhou Yanjie <zhouyanjie@zoho.com> 5 */ 6 7 #include <linux/clk-provider.h> 8 #include <linux/delay.h> 9 #include <linux/of.h> 10 #include <dt-bindings/clock/x1000-cgu.h> 11 #include "cgu.h" 12 #include "pm.h" 13 14 /* CGU register offsets */ 15 #define CGU_REG_CPCCR 0x00 16 #define CGU_REG_APLL 0x10 17 #define CGU_REG_MPLL 0x14 18 #define CGU_REG_CLKGR 0x20 19 #define CGU_REG_OPCR 0x24 20 #define CGU_REG_DDRCDR 0x2c 21 #define CGU_REG_MACCDR 0x54 22 #define CGU_REG_I2SCDR 0x60 23 #define CGU_REG_LPCDR 0x64 24 #define CGU_REG_MSC0CDR 0x68 25 #define CGU_REG_I2SCDR1 0x70 26 #define CGU_REG_SSICDR 0x74 27 #define CGU_REG_CIMCDR 0x7c 28 #define CGU_REG_PCMCDR 0x84 29 #define CGU_REG_MSC1CDR 0xa4 30 #define CGU_REG_CMP_INTR 0xb0 31 #define CGU_REG_CMP_INTRE 0xb4 32 #define CGU_REG_DRCG 0xd0 33 #define CGU_REG_CPCSR 0xd4 34 #define CGU_REG_PCMCDR1 0xe0 35 #define CGU_REG_MACPHYC 0xe8 36 37 /* bits within the OPCR register */ 38 #define OPCR_SPENDN0 BIT(7) 39 #define OPCR_SPENDN1 BIT(6) 40 41 static struct ingenic_cgu *cgu; 42 43 static const s8 pll_od_encoding[8] = { 44 0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3, 45 }; 46 47 static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = { 48 49 /* External clocks */ 50 51 [X1000_CLK_EXCLK] = { "ext", CGU_CLK_EXT }, 52 [X1000_CLK_RTCLK] = { "rtc", CGU_CLK_EXT }, 53 54 /* PLLs */ 55 56 [X1000_CLK_APLL] = { 57 "apll", CGU_CLK_PLL, 58 .parents = { X1000_CLK_EXCLK, -1, -1, -1 }, 59 .pll = { 60 .reg = CGU_REG_APLL, 61 .m_shift = 24, 62 .m_bits = 7, 63 .m_offset = 1, 64 .n_shift = 18, 65 .n_bits = 5, 66 .n_offset = 1, 67 .od_shift = 16, 68 .od_bits = 2, 69 .od_max = 8, 70 .od_encoding = pll_od_encoding, 71 .bypass_bit = 9, 72 .enable_bit = 8, 73 .stable_bit = 10, 74 }, 75 }, 76 77 [X1000_CLK_MPLL] = { 78 "mpll", CGU_CLK_PLL, 79 .parents = { X1000_CLK_EXCLK, -1, -1, -1 }, 80 .pll = { 81 .reg = CGU_REG_MPLL, 82 .m_shift = 24, 83 .m_bits = 7, 84 .m_offset = 1, 85 .n_shift = 18, 86 .n_bits = 5, 87 .n_offset = 1, 88 .od_shift = 16, 89 .od_bits = 2, 90 .od_max = 8, 91 .od_encoding = pll_od_encoding, 92 .bypass_bit = 6, 93 .enable_bit = 7, 94 .stable_bit = 0, 95 }, 96 }, 97 98 /* Muxes & dividers */ 99 100 [X1000_CLK_SCLKA] = { 101 "sclk_a", CGU_CLK_MUX, 102 .parents = { -1, X1000_CLK_EXCLK, X1000_CLK_APLL, -1 }, 103 .mux = { CGU_REG_CPCCR, 30, 2 }, 104 }, 105 106 [X1000_CLK_CPUMUX] = { 107 "cpu_mux", CGU_CLK_MUX, 108 .parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 }, 109 .mux = { CGU_REG_CPCCR, 28, 2 }, 110 }, 111 112 [X1000_CLK_CPU] = { 113 "cpu", CGU_CLK_DIV, 114 .parents = { X1000_CLK_CPUMUX, -1, -1, -1 }, 115 .div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1 }, 116 }, 117 118 [X1000_CLK_L2CACHE] = { 119 "l2cache", CGU_CLK_DIV, 120 .parents = { X1000_CLK_CPUMUX, -1, -1, -1 }, 121 .div = { CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1 }, 122 }, 123 124 [X1000_CLK_AHB0] = { 125 "ahb0", CGU_CLK_MUX | CGU_CLK_DIV, 126 .parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 }, 127 .mux = { CGU_REG_CPCCR, 26, 2 }, 128 .div = { CGU_REG_CPCCR, 8, 1, 4, 21, -1, -1 }, 129 }, 130 131 [X1000_CLK_AHB2PMUX] = { 132 "ahb2_apb_mux", CGU_CLK_MUX, 133 .parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 }, 134 .mux = { CGU_REG_CPCCR, 24, 2 }, 135 }, 136 137 [X1000_CLK_AHB2] = { 138 "ahb2", CGU_CLK_DIV, 139 .parents = { X1000_CLK_AHB2PMUX, -1, -1, -1 }, 140 .div = { CGU_REG_CPCCR, 12, 1, 4, 20, -1, -1 }, 141 }, 142 143 [X1000_CLK_PCLK] = { 144 "pclk", CGU_CLK_DIV, 145 .parents = { X1000_CLK_AHB2PMUX, -1, -1, -1 }, 146 .div = { CGU_REG_CPCCR, 16, 1, 4, 20, -1, -1 }, 147 }, 148 149 [X1000_CLK_DDR] = { 150 "ddr", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE, 151 .parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 }, 152 .mux = { CGU_REG_DDRCDR, 30, 2 }, 153 .div = { CGU_REG_DDRCDR, 0, 1, 4, 29, 28, 27 }, 154 .gate = { CGU_REG_CLKGR, 31 }, 155 }, 156 157 [X1000_CLK_MAC] = { 158 "mac", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE, 159 .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL}, 160 .mux = { CGU_REG_MACCDR, 31, 1 }, 161 .div = { CGU_REG_MACCDR, 0, 1, 8, 29, 28, 27 }, 162 .gate = { CGU_REG_CLKGR, 25 }, 163 }, 164 165 [X1000_CLK_MSCMUX] = { 166 "msc_mux", CGU_CLK_MUX, 167 .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL}, 168 .mux = { CGU_REG_MSC0CDR, 31, 1 }, 169 }, 170 171 [X1000_CLK_MSC0] = { 172 "msc0", CGU_CLK_DIV | CGU_CLK_GATE, 173 .parents = { X1000_CLK_MSCMUX, -1, -1, -1 }, 174 .div = { CGU_REG_MSC0CDR, 0, 2, 8, 29, 28, 27 }, 175 .gate = { CGU_REG_CLKGR, 4 }, 176 }, 177 178 [X1000_CLK_MSC1] = { 179 "msc1", CGU_CLK_DIV | CGU_CLK_GATE, 180 .parents = { X1000_CLK_MSCMUX, -1, -1, -1 }, 181 .div = { CGU_REG_MSC1CDR, 0, 2, 8, 29, 28, 27 }, 182 .gate = { CGU_REG_CLKGR, 5 }, 183 }, 184 185 [X1000_CLK_SSIPLL] = { 186 "ssi_pll", CGU_CLK_MUX | CGU_CLK_DIV, 187 .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL, -1, -1 }, 188 .mux = { CGU_REG_SSICDR, 31, 1 }, 189 .div = { CGU_REG_SSICDR, 0, 1, 8, 29, 28, 27 }, 190 }, 191 192 [X1000_CLK_SSIMUX] = { 193 "ssi_mux", CGU_CLK_MUX, 194 .parents = { X1000_CLK_EXCLK, X1000_CLK_SSIPLL, -1, -1 }, 195 .mux = { CGU_REG_SSICDR, 30, 1 }, 196 }, 197 198 /* Gate-only clocks */ 199 200 [X1000_CLK_SFC] = { 201 "sfc", CGU_CLK_GATE, 202 .parents = { X1000_CLK_SSIPLL, -1, -1, -1 }, 203 .gate = { CGU_REG_CLKGR, 2 }, 204 }, 205 206 [X1000_CLK_I2C0] = { 207 "i2c0", CGU_CLK_GATE, 208 .parents = { X1000_CLK_PCLK, -1, -1, -1 }, 209 .gate = { CGU_REG_CLKGR, 7 }, 210 }, 211 212 [X1000_CLK_I2C1] = { 213 "i2c1", CGU_CLK_GATE, 214 .parents = { X1000_CLK_PCLK, -1, -1, -1 }, 215 .gate = { CGU_REG_CLKGR, 8 }, 216 }, 217 218 [X1000_CLK_I2C2] = { 219 "i2c2", CGU_CLK_GATE, 220 .parents = { X1000_CLK_PCLK, -1, -1, -1 }, 221 .gate = { CGU_REG_CLKGR, 9 }, 222 }, 223 224 [X1000_CLK_UART0] = { 225 "uart0", CGU_CLK_GATE, 226 .parents = { X1000_CLK_EXCLK, -1, -1, -1 }, 227 .gate = { CGU_REG_CLKGR, 14 }, 228 }, 229 230 [X1000_CLK_UART1] = { 231 "uart1", CGU_CLK_GATE, 232 .parents = { X1000_CLK_EXCLK, -1, -1, -1 }, 233 .gate = { CGU_REG_CLKGR, 15 }, 234 }, 235 236 [X1000_CLK_UART2] = { 237 "uart2", CGU_CLK_GATE, 238 .parents = { X1000_CLK_EXCLK, -1, -1, -1 }, 239 .gate = { CGU_REG_CLKGR, 16 }, 240 }, 241 242 [X1000_CLK_SSI] = { 243 "ssi", CGU_CLK_GATE, 244 .parents = { X1000_CLK_SSIMUX, -1, -1, -1 }, 245 .gate = { CGU_REG_CLKGR, 19 }, 246 }, 247 248 [X1000_CLK_PDMA] = { 249 "pdma", CGU_CLK_GATE, 250 .parents = { X1000_CLK_EXCLK, -1, -1, -1 }, 251 .gate = { CGU_REG_CLKGR, 21 }, 252 }, 253 }; 254 255 static void __init x1000_cgu_init(struct device_node *np) 256 { 257 int retval; 258 259 cgu = ingenic_cgu_new(x1000_cgu_clocks, 260 ARRAY_SIZE(x1000_cgu_clocks), np); 261 if (!cgu) { 262 pr_err("%s: failed to initialise CGU\n", __func__); 263 return; 264 } 265 266 retval = ingenic_cgu_register_clocks(cgu); 267 if (retval) { 268 pr_err("%s: failed to register CGU Clocks\n", __func__); 269 return; 270 } 271 272 ingenic_cgu_register_syscore_ops(cgu); 273 } 274 CLK_OF_DECLARE(x1000_cgu, "ingenic,x1000-cgu", x1000_cgu_init); 275