1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2024 ASPEED Technology Inc. 4 * Author: Ryan Chen <ryan_chen@aspeedtech.com> 5 */ 6 #include <linux/auxiliary_bus.h> 7 #include <linux/bitfield.h> 8 #include <linux/clk-provider.h> 9 #include <linux/io.h> 10 #include <linux/mod_devicetable.h> 11 #include <linux/platform_device.h> 12 #include <linux/slab.h> 13 #include <linux/units.h> 14 15 #include <dt-bindings/clock/aspeed,ast2700-scu.h> 16 17 /* SOC0 */ 18 #define SCU0_HWSTRAP1 0x010 19 #define SCU0_CLK_STOP 0x240 20 #define SCU0_CLK_SEL1 0x280 21 #define SCU0_CLK_SEL2 0x284 22 #define GET_USB_REFCLK_DIV(x) ((GENMASK(23, 20) & (x)) >> 20) 23 #define UART_DIV13_EN BIT(30) 24 #define SCU0_HPLL_PARAM 0x300 25 #define SCU0_DPLL_PARAM 0x308 26 #define SCU0_MPLL_PARAM 0x310 27 #define SCU0_D0CLK_PARAM 0x320 28 #define SCU0_D1CLK_PARAM 0x330 29 #define SCU0_CRT0CLK_PARAM 0x340 30 #define SCU0_CRT1CLK_PARAM 0x350 31 #define SCU0_MPHYCLK_PARAM 0x360 32 33 /* SOC1 */ 34 #define SCU1_REVISION_ID 0x0 35 #define REVISION_ID GENMASK(23, 16) 36 #define SCU1_CLK_STOP 0x240 37 #define SCU1_CLK_STOP2 0x260 38 #define SCU1_CLK_SEL1 0x280 39 #define SCU1_CLK_SEL2 0x284 40 #define SCU1_CLK_I3C_DIV_MASK GENMASK(25, 23) 41 #define SCU1_CLK_I3C_DIV(n) ((n) - 1) 42 #define UXCLK_MASK GENMASK(1, 0) 43 #define HUXCLK_MASK GENMASK(4, 3) 44 #define SCU1_HPLL_PARAM 0x300 45 #define SCU1_APLL_PARAM 0x310 46 #define SCU1_DPLL_PARAM 0x320 47 #define SCU1_UXCLK_CTRL 0x330 48 #define SCU1_HUXCLK_CTRL 0x334 49 #define SCU1_MAC12_CLK_DLY 0x390 50 #define SCU1_MAC12_CLK_DLY_100M 0x394 51 #define SCU1_MAC12_CLK_DLY_10M 0x398 52 53 enum ast2700_clk_type { 54 CLK_MUX, 55 CLK_PLL, 56 CLK_HPLL, 57 CLK_GATE, 58 CLK_MISC, 59 CLK_FIXED, 60 CLK_DIVIDER, 61 CLK_UART_PLL, 62 CLK_GATE_ASPEED, 63 CLK_FIXED_FACTOR, 64 CLK_FIXED_DISPLAY, 65 }; 66 67 struct ast2700_clk_fixed_factor_data { 68 unsigned int mult; 69 unsigned int div; 70 int parent_id; 71 }; 72 73 struct ast2700_clk_gate_data { 74 int parent_id; 75 u32 flags; 76 u32 reg; 77 u8 bit; 78 }; 79 80 struct ast2700_clk_mux_data { 81 const struct clk_hw **parent_hws; 82 const unsigned int *parent_ids; 83 unsigned int num_parents; 84 u8 bit_shift; 85 u8 bit_width; 86 u32 reg; 87 }; 88 89 struct ast2700_clk_div_data { 90 const struct clk_div_table *div_table; 91 unsigned int parent_id; 92 u8 bit_shift; 93 u8 bit_width; 94 u32 reg; 95 }; 96 97 struct ast2700_clk_pll_data { 98 unsigned int parent_id; 99 u32 reg; 100 }; 101 102 struct ast2700_clk_fixed_rate_data { 103 unsigned long fixed_rate; 104 }; 105 106 struct ast2700_clk_display_fixed_data { 107 u32 reg; 108 }; 109 110 struct ast2700_clk_info { 111 const char *name; 112 u32 id; 113 u32 reg; 114 u32 type; 115 union { 116 struct ast2700_clk_fixed_factor_data factor; 117 struct ast2700_clk_fixed_rate_data rate; 118 struct ast2700_clk_display_fixed_data display_rate; 119 struct ast2700_clk_gate_data gate; 120 struct ast2700_clk_div_data div; 121 struct ast2700_clk_pll_data pll; 122 struct ast2700_clk_mux_data mux; 123 } data; 124 }; 125 126 struct ast2700_clk_data { 127 const struct ast2700_clk_info *clk_info; 128 unsigned int nr_clks; 129 const int scu; 130 }; 131 132 struct ast2700_clk_ctrl { 133 const struct ast2700_clk_data *clk_data; 134 struct device *dev; 135 void __iomem *base; 136 spinlock_t lock; /* clk lock */ 137 }; 138 139 static const struct clk_div_table ast2700_rgmii_div_table[] = { 140 { 0x0, 4 }, 141 { 0x1, 4 }, 142 { 0x2, 6 }, 143 { 0x3, 8 }, 144 { 0x4, 10 }, 145 { 0x5, 12 }, 146 { 0x6, 14 }, 147 { 0x7, 16 }, 148 { 0 } 149 }; 150 151 static const struct clk_div_table ast2700_rmii_div_table[] = { 152 { 0x0, 8 }, 153 { 0x1, 8 }, 154 { 0x2, 12 }, 155 { 0x3, 16 }, 156 { 0x4, 20 }, 157 { 0x5, 24 }, 158 { 0x6, 28 }, 159 { 0x7, 32 }, 160 { 0 } 161 }; 162 163 static const struct clk_div_table ast2700_clk_div_table[] = { 164 { 0x0, 2 }, 165 { 0x1, 2 }, 166 { 0x2, 3 }, 167 { 0x3, 4 }, 168 { 0x4, 5 }, 169 { 0x5, 6 }, 170 { 0x6, 7 }, 171 { 0x7, 8 }, 172 { 0 } 173 }; 174 175 static const struct clk_div_table ast2700_clk_div_table2[] = { 176 { 0x0, 2 }, 177 { 0x1, 4 }, 178 { 0x2, 6 }, 179 { 0x3, 8 }, 180 { 0x4, 10 }, 181 { 0x5, 12 }, 182 { 0x6, 14 }, 183 { 0x7, 16 }, 184 { 0 } 185 }; 186 187 static const struct clk_div_table ast2700_hclk_div_table[] = { 188 { 0x0, 6 }, 189 { 0x1, 5 }, 190 { 0x2, 4 }, 191 { 0x3, 7 }, 192 { 0 } 193 }; 194 195 static const struct clk_div_table ast2700_clk_uart_div_table[] = { 196 { 0x0, 1 }, 197 { 0x1, 13 }, 198 { 0 } 199 }; 200 201 /* soc 0 */ 202 static const unsigned int psp_parent_ids[] = { 203 SCU0_CLK_MPLL, 204 SCU0_CLK_HPLL, 205 SCU0_CLK_HPLL, 206 SCU0_CLK_HPLL, 207 SCU0_CLK_MPLL_DIV2, 208 SCU0_CLK_HPLL_DIV2, 209 SCU0_CLK_HPLL, 210 SCU0_CLK_HPLL 211 }; 212 213 static const struct clk_hw *psp_parent_hws[ARRAY_SIZE(psp_parent_ids)]; 214 215 static const unsigned int hclk_parent_ids[] = { 216 SCU0_CLK_HPLL, 217 SCU0_CLK_MPLL 218 }; 219 220 static const struct clk_hw *hclk_parent_hws[ARRAY_SIZE(hclk_parent_ids)]; 221 222 static const unsigned int emmc_parent_ids[] = { 223 SCU0_CLK_MPLL_DIV4, 224 SCU0_CLK_HPLL_DIV4 225 }; 226 227 static const struct clk_hw *emmc_parent_hws[ARRAY_SIZE(emmc_parent_ids)]; 228 229 static const unsigned int mphy_parent_ids[] = { 230 SCU0_CLK_MPLL, 231 SCU0_CLK_HPLL, 232 SCU0_CLK_DPLL, 233 SCU0_CLK_192M 234 }; 235 236 static const struct clk_hw *mphy_parent_hws[ARRAY_SIZE(mphy_parent_ids)]; 237 238 static const unsigned int u2phy_parent_ids[] = { 239 SCU0_CLK_MPLL, 240 SCU0_CLK_HPLL 241 }; 242 243 static const struct clk_hw *u2phy_parent_hws[ARRAY_SIZE(u2phy_parent_ids)]; 244 245 static const unsigned int uart_parent_ids[] = { 246 SCU0_CLK_24M, 247 SCU0_CLK_192M 248 }; 249 250 static const struct clk_hw *uart_parent_hws[ARRAY_SIZE(uart_parent_ids)]; 251 252 /* soc 1 */ 253 static const unsigned int uartx_parent_ids[] = { 254 SCU1_CLK_UARTX, 255 SCU1_CLK_HUARTX 256 }; 257 258 static const struct clk_hw *uartx_parent_hws[ARRAY_SIZE(uartx_parent_ids)]; 259 260 static const unsigned int uxclk_parent_ids[] = { 261 SCU1_CLK_APLL_DIV4, 262 SCU1_CLK_APLL_DIV2, 263 SCU1_CLK_APLL, 264 SCU1_CLK_HPLL 265 }; 266 267 static const struct clk_hw *uxclk_parent_hws[ARRAY_SIZE(uxclk_parent_ids)]; 268 269 static const unsigned int sdclk_parent_ids[] = { 270 SCU1_CLK_HPLL, 271 SCU1_CLK_APLL 272 }; 273 274 static const struct clk_hw *sdclk_parent_hws[ARRAY_SIZE(sdclk_parent_ids)]; 275 276 #define FIXED_CLK(_id, _name, _rate) \ 277 { \ 278 .id = _id, \ 279 .type = CLK_FIXED, \ 280 .name = _name, \ 281 .data = { .rate = { .fixed_rate = _rate, } }, \ 282 } 283 284 #define FIXED_DISPLAY_CLK(_id, _name, _reg) \ 285 { \ 286 .id = _id, \ 287 .type = CLK_FIXED_DISPLAY, \ 288 .name = _name, \ 289 .data = { .display_rate = { .reg = _reg } }, \ 290 } 291 292 #define PLL_CLK(_id, _type, _name, _parent_id, _reg) \ 293 { \ 294 .id = _id, \ 295 .type = _type, \ 296 .name = _name, \ 297 .data = { .pll = { \ 298 .parent_id = _parent_id, \ 299 .reg = _reg, \ 300 } }, \ 301 } 302 303 #define MUX_CLK(_id, _name, _parent_ids, _num_parents, _parent_hws, _reg, _shift, _width) \ 304 { \ 305 .id = _id, \ 306 .type = CLK_MUX, \ 307 .name = _name, \ 308 .data = { \ 309 .mux = { \ 310 .parent_ids = _parent_ids, \ 311 .parent_hws = _parent_hws, \ 312 .num_parents = _num_parents, \ 313 .reg = (_reg), \ 314 .bit_shift = _shift, \ 315 .bit_width = _width, \ 316 }, \ 317 }, \ 318 } 319 320 #define DIVIDER_CLK(_id, _name, _parent_id, _reg, _shift, _width, _div_table) \ 321 { \ 322 .id = _id, \ 323 .type = CLK_DIVIDER, \ 324 .name = _name, \ 325 .data = { \ 326 .div = { \ 327 .parent_id = _parent_id, \ 328 .reg = _reg, \ 329 .bit_shift = _shift, \ 330 .bit_width = _width, \ 331 .div_table = _div_table, \ 332 }, \ 333 }, \ 334 } 335 336 #define FIXED_FACTOR_CLK(_id, _name, _parent_id, _mult, _div) \ 337 { \ 338 .id = _id, \ 339 .type = CLK_FIXED_FACTOR, \ 340 .name = _name, \ 341 .data = { .factor = { .parent_id = _parent_id, .mult = _mult, .div = _div, } }, \ 342 } 343 344 #define GATE_CLK(_id, _type, _name, _parent_id, _reg, _bit, _flags) \ 345 { \ 346 .id = _id, \ 347 .type = _type, \ 348 .name = _name, \ 349 .data = { \ 350 .gate = { \ 351 .parent_id = _parent_id, \ 352 .reg = _reg, \ 353 .bit = _bit, \ 354 .flags = _flags, \ 355 }, \ 356 }, \ 357 } 358 359 static const struct ast2700_clk_info ast2700_scu0_clk_info[] __initconst = { 360 FIXED_CLK(SCU0_CLKIN, "soc0-clkin", 25 * HZ_PER_MHZ), 361 FIXED_CLK(SCU0_CLK_24M, "soc0-clk24Mhz", 24 * HZ_PER_MHZ), 362 FIXED_CLK(SCU0_CLK_192M, "soc0-clk192Mhz", 192 * HZ_PER_MHZ), 363 FIXED_CLK(SCU0_CLK_U2PHY_CLK12M, "u2phy_clk12m", 12 * HZ_PER_MHZ), 364 FIXED_DISPLAY_CLK(SCU0_CLK_D0, "d0clk", SCU0_D0CLK_PARAM), 365 FIXED_DISPLAY_CLK(SCU0_CLK_D1, "d1clk", SCU0_D1CLK_PARAM), 366 FIXED_DISPLAY_CLK(SCU0_CLK_CRT0, "crt0clk", SCU0_CRT0CLK_PARAM), 367 FIXED_DISPLAY_CLK(SCU0_CLK_CRT1, "crt1clk", SCU0_CRT1CLK_PARAM), 368 PLL_CLK(SCU0_CLK_HPLL, CLK_HPLL, "soc0-hpll", SCU0_CLKIN, SCU0_HPLL_PARAM), 369 PLL_CLK(SCU0_CLK_DPLL, CLK_PLL, "soc0-dpll", SCU0_CLKIN, SCU0_DPLL_PARAM), 370 PLL_CLK(SCU0_CLK_MPLL, CLK_PLL, "soc0-mpll", SCU0_CLKIN, SCU0_MPLL_PARAM), 371 FIXED_FACTOR_CLK(SCU0_CLK_HPLL_DIV2, "soc0-hpll_div2", SCU0_CLK_HPLL, 1, 2), 372 FIXED_FACTOR_CLK(SCU0_CLK_HPLL_DIV4, "soc0-hpll_div4", SCU0_CLK_HPLL, 1, 4), 373 FIXED_FACTOR_CLK(SCU0_CLK_MPLL_DIV2, "soc0-mpll_div2", SCU0_CLK_MPLL, 1, 2), 374 FIXED_FACTOR_CLK(SCU0_CLK_MPLL_DIV4, "soc0-mpll_div4", SCU0_CLK_MPLL, 1, 4), 375 FIXED_FACTOR_CLK(SCU0_CLK_MPLL_DIV8, "soc0-mpll_div8", SCU0_CLK_MPLL, 1, 8), 376 FIXED_FACTOR_CLK(SCU0_CLK_AXI1, "axi1clk", SCU0_CLK_MPLL, 1, 4), 377 MUX_CLK(SCU0_CLK_PSP, "pspclk", psp_parent_ids, ARRAY_SIZE(psp_parent_ids), 378 psp_parent_hws, SCU0_HWSTRAP1, 2, 3), 379 FIXED_FACTOR_CLK(SCU0_CLK_AXI0, "axi0clk", SCU0_CLK_PSP, 1, 2), 380 MUX_CLK(SCU0_CLK_AHBMUX, "soc0-ahbmux", hclk_parent_ids, ARRAY_SIZE(hclk_parent_ids), 381 hclk_parent_hws, SCU0_HWSTRAP1, 7, 1), 382 MUX_CLK(SCU0_CLK_EMMCMUX, "emmcsrc-mux", emmc_parent_ids, ARRAY_SIZE(emmc_parent_ids), 383 emmc_parent_hws, SCU0_CLK_SEL1, 11, 1), 384 MUX_CLK(SCU0_CLK_MPHYSRC, "mphysrc", mphy_parent_ids, ARRAY_SIZE(mphy_parent_ids), 385 mphy_parent_hws, SCU0_CLK_SEL2, 18, 2), 386 MUX_CLK(SCU0_CLK_U2PHY_REFCLKSRC, "u2phy_refclksrc", u2phy_parent_ids, 387 ARRAY_SIZE(u2phy_parent_ids), u2phy_parent_hws, SCU0_CLK_SEL2, 23, 1), 388 MUX_CLK(SCU0_CLK_UART, "soc0-uartclk", uart_parent_ids, ARRAY_SIZE(uart_parent_ids), 389 uart_parent_hws, SCU0_CLK_SEL2, 14, 1), 390 PLL_CLK(SCU0_CLK_MPHY, CLK_MISC, "mphyclk", SCU0_CLK_MPHYSRC, SCU0_MPHYCLK_PARAM), 391 PLL_CLK(SCU0_CLK_U2PHY_REFCLK, CLK_MISC, "u2phy_refclk", SCU0_CLK_U2PHY_REFCLKSRC, 392 SCU0_CLK_SEL2), 393 DIVIDER_CLK(SCU0_CLK_AHB, "soc0-ahb", SCU0_CLK_AHBMUX, 394 SCU0_HWSTRAP1, 5, 2, ast2700_hclk_div_table), 395 DIVIDER_CLK(SCU0_CLK_EMMC, "emmcclk", SCU0_CLK_EMMCMUX, 396 SCU0_CLK_SEL1, 12, 3, ast2700_clk_div_table2), 397 DIVIDER_CLK(SCU0_CLK_APB, "soc0-apb", SCU0_CLK_AXI0, 398 SCU0_CLK_SEL1, 23, 3, ast2700_clk_div_table2), 399 DIVIDER_CLK(SCU0_CLK_HPLL_DIV_AHB, "soc0-hpll-ahb", SCU0_CLK_HPLL, 400 SCU0_HWSTRAP1, 5, 2, ast2700_hclk_div_table), 401 DIVIDER_CLK(SCU0_CLK_MPLL_DIV_AHB, "soc0-mpll-ahb", SCU0_CLK_MPLL, 402 SCU0_HWSTRAP1, 5, 2, ast2700_hclk_div_table), 403 DIVIDER_CLK(SCU0_CLK_UART4, "uart4clk", SCU0_CLK_UART, 404 SCU0_CLK_SEL2, 30, 1, ast2700_clk_uart_div_table), 405 GATE_CLK(SCU0_CLK_GATE_MCLK, CLK_GATE_ASPEED, "mclk-gate", SCU0_CLK_MPLL, 406 SCU0_CLK_STOP, 0, CLK_IS_CRITICAL), 407 GATE_CLK(SCU0_CLK_GATE_ECLK, CLK_GATE_ASPEED, "eclk-gate", -1, SCU0_CLK_STOP, 1, 0), 408 GATE_CLK(SCU0_CLK_GATE_2DCLK, CLK_GATE_ASPEED, "gclk-gate", -1, SCU0_CLK_STOP, 2, 0), 409 GATE_CLK(SCU0_CLK_GATE_VCLK, CLK_GATE_ASPEED, "vclk-gate", -1, SCU0_CLK_STOP, 3, 0), 410 GATE_CLK(SCU0_CLK_GATE_BCLK, CLK_GATE_ASPEED, "bclk-gate", -1, 411 SCU0_CLK_STOP, 4, CLK_IS_CRITICAL), 412 GATE_CLK(SCU0_CLK_GATE_VGA0CLK, CLK_GATE_ASPEED, "vga0clk-gate", -1, 413 SCU0_CLK_STOP, 5, CLK_IS_CRITICAL), 414 GATE_CLK(SCU0_CLK_GATE_REFCLK, CLK_GATE_ASPEED, "soc0-refclk-gate", SCU0_CLKIN, 415 SCU0_CLK_STOP, 6, CLK_IS_CRITICAL), 416 GATE_CLK(SCU0_CLK_GATE_PORTBUSB2CLK, CLK_GATE_ASPEED, "portb-usb2clk-gate", -1, 417 SCU0_CLK_STOP, 7, 0), 418 GATE_CLK(SCU0_CLK_GATE_UHCICLK, CLK_GATE_ASPEED, "uhciclk-gate", -1, SCU0_CLK_STOP, 9, 0), 419 GATE_CLK(SCU0_CLK_GATE_VGA1CLK, CLK_GATE_ASPEED, "vga1clk-gate", -1, 420 SCU0_CLK_STOP, 10, CLK_IS_CRITICAL), 421 GATE_CLK(SCU0_CLK_GATE_DDRPHYCLK, CLK_GATE_ASPEED, "ddrphy-gate", -1, 422 SCU0_CLK_STOP, 11, CLK_IS_CRITICAL), 423 GATE_CLK(SCU0_CLK_GATE_E2M0CLK, CLK_GATE_ASPEED, "e2m0clk-gate", -1, 424 SCU0_CLK_STOP, 12, CLK_IS_CRITICAL), 425 GATE_CLK(SCU0_CLK_GATE_HACCLK, CLK_GATE_ASPEED, "hacclk-gate", -1, SCU0_CLK_STOP, 13, 0), 426 GATE_CLK(SCU0_CLK_GATE_PORTAUSB2CLK, CLK_GATE_ASPEED, "porta-usb2clk-gate", -1, 427 SCU0_CLK_STOP, 14, 0), 428 GATE_CLK(SCU0_CLK_GATE_UART4CLK, CLK_GATE_ASPEED, "uart4clk-gate", SCU0_CLK_UART4, 429 SCU0_CLK_STOP, 15, CLK_IS_CRITICAL), 430 GATE_CLK(SCU0_CLK_GATE_SLICLK, CLK_GATE_ASPEED, "soc0-sliclk-gate", -1, 431 SCU0_CLK_STOP, 16, CLK_IS_CRITICAL), 432 GATE_CLK(SCU0_CLK_GATE_DACCLK, CLK_GATE_ASPEED, "dacclk-gate", -1, 433 SCU0_CLK_STOP, 17, CLK_IS_CRITICAL), 434 GATE_CLK(SCU0_CLK_GATE_DP, CLK_GATE_ASPEED, "dpclk-gate", -1, 435 SCU0_CLK_STOP, 18, CLK_IS_CRITICAL), 436 GATE_CLK(SCU0_CLK_GATE_E2M1CLK, CLK_GATE_ASPEED, "e2m1clk-gate", -1, 437 SCU0_CLK_STOP, 19, CLK_IS_CRITICAL), 438 GATE_CLK(SCU0_CLK_GATE_CRT0CLK, CLK_GATE_ASPEED, "crt0clk-gate", -1, 439 SCU0_CLK_STOP, 20, 0), 440 GATE_CLK(SCU0_CLK_GATE_CRT1CLK, CLK_GATE_ASPEED, "crt1clk-gate", -1, 441 SCU0_CLK_STOP, 21, 0), 442 GATE_CLK(SCU0_CLK_GATE_ECDSACLK, CLK_GATE_ASPEED, "eccclk-gate", -1, 443 SCU0_CLK_STOP, 23, 0), 444 GATE_CLK(SCU0_CLK_GATE_RSACLK, CLK_GATE_ASPEED, "rsaclk-gate", -1, 445 SCU0_CLK_STOP, 24, 0), 446 GATE_CLK(SCU0_CLK_GATE_RVAS0CLK, CLK_GATE_ASPEED, "rvas0clk-gate", -1, 447 SCU0_CLK_STOP, 25, 0), 448 GATE_CLK(SCU0_CLK_GATE_UFSCLK, CLK_GATE_ASPEED, "ufsclk-gate", -1, 449 SCU0_CLK_STOP, 26, 0), 450 GATE_CLK(SCU0_CLK_GATE_EMMCCLK, CLK_GATE_ASPEED, "emmcclk-gate", SCU0_CLK_EMMC, 451 SCU0_CLK_STOP, 27, 0), 452 GATE_CLK(SCU0_CLK_GATE_RVAS1CLK, CLK_GATE_ASPEED, "rvas1clk-gate", -1, 453 SCU0_CLK_STOP, 28, 0), 454 }; 455 456 static const struct ast2700_clk_info ast2700_scu1_clk_info[] __initconst = { 457 FIXED_CLK(SCU1_CLKIN, "soc1-clkin", 25 * HZ_PER_MHZ), 458 PLL_CLK(SCU1_CLK_HPLL, CLK_PLL, "soc1-hpll", SCU1_CLKIN, SCU1_HPLL_PARAM), 459 PLL_CLK(SCU1_CLK_APLL, CLK_PLL, "soc1-apll", SCU1_CLKIN, SCU1_APLL_PARAM), 460 PLL_CLK(SCU1_CLK_DPLL, CLK_PLL, "soc1-dpll", SCU1_CLKIN, SCU1_DPLL_PARAM), 461 FIXED_FACTOR_CLK(SCU1_CLK_APLL_DIV2, "soc1-apll_div2", SCU1_CLK_APLL, 1, 2), 462 FIXED_FACTOR_CLK(SCU1_CLK_APLL_DIV4, "soc1-apll_div4", SCU1_CLK_APLL, 1, 4), 463 FIXED_FACTOR_CLK(SCU1_CLK_CAN, "canclk", SCU1_CLK_APLL, 1, 10), 464 DIVIDER_CLK(SCU1_CLK_APB, "soc1-apb", SCU1_CLK_HPLL, 465 SCU1_CLK_SEL1, 18, 3, ast2700_clk_div_table2), 466 DIVIDER_CLK(SCU1_CLK_RMII, "rmii", SCU1_CLK_HPLL, 467 SCU1_CLK_SEL1, 21, 3, ast2700_rmii_div_table), 468 DIVIDER_CLK(SCU1_CLK_RGMII, "rgmii", SCU1_CLK_HPLL, 469 SCU1_CLK_SEL1, 25, 3, ast2700_rgmii_div_table), 470 DIVIDER_CLK(SCU1_CLK_MACHCLK, "machclk", SCU1_CLK_HPLL, 471 SCU1_CLK_SEL1, 29, 3, ast2700_clk_div_table), 472 DIVIDER_CLK(SCU1_CLK_APLL_DIVN, "soc1-apll_divn", 473 SCU1_CLK_APLL, SCU1_CLK_SEL2, 8, 3, ast2700_clk_div_table), 474 DIVIDER_CLK(SCU1_CLK_AHB, "soc1-ahb", SCU1_CLK_HPLL, 475 SCU1_CLK_SEL2, 20, 3, ast2700_clk_div_table), 476 DIVIDER_CLK(SCU1_CLK_I3C, "soc1-i3c", SCU1_CLK_HPLL, 477 SCU1_CLK_SEL2, 23, 3, ast2700_clk_div_table), 478 MUX_CLK(SCU1_CLK_SDMUX, "sdclk-mux", sdclk_parent_ids, ARRAY_SIZE(sdclk_parent_ids), 479 sdclk_parent_hws, SCU1_CLK_SEL1, 13, 1), 480 MUX_CLK(SCU1_CLK_UXCLK, "uxclk", uxclk_parent_ids, ARRAY_SIZE(uxclk_parent_ids), 481 uxclk_parent_hws, SCU1_CLK_SEL2, 0, 2), 482 MUX_CLK(SCU1_CLK_HUXCLK, "huxclk", uxclk_parent_ids, ARRAY_SIZE(uxclk_parent_ids), 483 uxclk_parent_hws, SCU1_CLK_SEL2, 3, 2), 484 DIVIDER_CLK(SCU1_CLK_SDCLK, "sdclk", SCU1_CLK_SDMUX, 485 SCU1_CLK_SEL1, 14, 3, ast2700_clk_div_table), 486 PLL_CLK(SCU1_CLK_UARTX, CLK_UART_PLL, "uartxclk", SCU1_CLK_UXCLK, SCU1_UXCLK_CTRL), 487 PLL_CLK(SCU1_CLK_HUARTX, CLK_UART_PLL, "huartxclk", SCU1_CLK_HUXCLK, SCU1_HUXCLK_CTRL), 488 MUX_CLK(SCU1_CLK_UART0, "uart0clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), 489 uartx_parent_hws, SCU1_CLK_SEL1, 0, 1), 490 MUX_CLK(SCU1_CLK_UART1, "uart1clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), 491 uartx_parent_hws, SCU1_CLK_SEL1, 1, 1), 492 MUX_CLK(SCU1_CLK_UART2, "uart2clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), 493 uartx_parent_hws, SCU1_CLK_SEL1, 2, 1), 494 MUX_CLK(SCU1_CLK_UART3, "uart3clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), 495 uartx_parent_hws, SCU1_CLK_SEL1, 3, 1), 496 MUX_CLK(SCU1_CLK_UART5, "uart5clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), 497 uartx_parent_hws, SCU1_CLK_SEL1, 5, 1), 498 MUX_CLK(SCU1_CLK_UART6, "uart6clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), 499 uartx_parent_hws, SCU1_CLK_SEL1, 6, 1), 500 MUX_CLK(SCU1_CLK_UART7, "uart7clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), 501 uartx_parent_hws, SCU1_CLK_SEL1, 7, 1), 502 MUX_CLK(SCU1_CLK_UART8, "uart8clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), 503 uartx_parent_hws, SCU1_CLK_SEL1, 8, 1), 504 MUX_CLK(SCU1_CLK_UART9, "uart9clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), 505 uartx_parent_hws, SCU1_CLK_SEL1, 9, 1), 506 MUX_CLK(SCU1_CLK_UART10, "uart10clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), 507 uartx_parent_hws, SCU1_CLK_SEL1, 10, 1), 508 MUX_CLK(SCU1_CLK_UART11, "uart11clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), 509 uartx_parent_hws, SCU1_CLK_SEL1, 11, 1), 510 MUX_CLK(SCU1_CLK_UART12, "uart12clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), 511 uartx_parent_hws, SCU1_CLK_SEL1, 12, 1), 512 FIXED_FACTOR_CLK(SCU1_CLK_UART13, "uart13clk", SCU1_CLK_HUARTX, 1, 1), 513 FIXED_FACTOR_CLK(SCU1_CLK_UART14, "uart14clk", SCU1_CLK_HUARTX, 1, 1), 514 GATE_CLK(SCU1_CLK_MAC0RCLK, CLK_GATE, "mac0rclk-gate", SCU1_CLK_RMII, 515 SCU1_MAC12_CLK_DLY, 29, 0), 516 GATE_CLK(SCU1_CLK_MAC1RCLK, CLK_GATE, "mac1rclk-gate", SCU1_CLK_RMII, 517 SCU1_MAC12_CLK_DLY, 30, 0), 518 GATE_CLK(SCU1_CLK_GATE_LCLK0, CLK_GATE_ASPEED, "lclk0-gate", -1, 519 SCU1_CLK_STOP, 0, CLK_IS_CRITICAL), 520 GATE_CLK(SCU1_CLK_GATE_LCLK1, CLK_GATE_ASPEED, "lclk1-gate", -1, 521 SCU1_CLK_STOP, 1, CLK_IS_CRITICAL), 522 GATE_CLK(SCU1_CLK_GATE_ESPI0CLK, CLK_GATE_ASPEED, "espi0clk-gate", -1, 523 SCU1_CLK_STOP, 2, CLK_IS_CRITICAL), 524 GATE_CLK(SCU1_CLK_GATE_ESPI1CLK, CLK_GATE_ASPEED, "espi1clk-gate", -1, 525 SCU1_CLK_STOP, 3, CLK_IS_CRITICAL), 526 GATE_CLK(SCU1_CLK_GATE_SDCLK, CLK_GATE_ASPEED, "sdclk-gate", SCU1_CLK_SDCLK, 527 SCU1_CLK_STOP, 4, CLK_IS_CRITICAL), 528 GATE_CLK(SCU1_CLK_GATE_IPEREFCLK, CLK_GATE_ASPEED, "soc1-iperefclk-gate", -1, 529 SCU1_CLK_STOP, 5, CLK_IS_CRITICAL), 530 GATE_CLK(SCU1_CLK_GATE_REFCLK, CLK_GATE_ASPEED, "soc1-refclk-gate", -1, 531 SCU1_CLK_STOP, 6, CLK_IS_CRITICAL), 532 GATE_CLK(SCU1_CLK_GATE_LPCHCLK, CLK_GATE_ASPEED, "lpchclk-gate", -1, 533 SCU1_CLK_STOP, 7, CLK_IS_CRITICAL), 534 GATE_CLK(SCU1_CLK_GATE_MAC0CLK, CLK_GATE_ASPEED, "mac0clk-gate", -1, 535 SCU1_CLK_STOP, 8, 0), 536 GATE_CLK(SCU1_CLK_GATE_MAC1CLK, CLK_GATE_ASPEED, "mac1clk-gate", -1, 537 SCU1_CLK_STOP, 9, 0), 538 GATE_CLK(SCU1_CLK_GATE_MAC2CLK, CLK_GATE_ASPEED, "mac2clk-gate", -1, 539 SCU1_CLK_STOP, 10, 0), 540 GATE_CLK(SCU1_CLK_GATE_UART0CLK, CLK_GATE_ASPEED, "uart0clk-gate", SCU1_CLK_UART0, 541 SCU1_CLK_STOP, 11, CLK_IS_CRITICAL), 542 GATE_CLK(SCU1_CLK_GATE_UART1CLK, CLK_GATE_ASPEED, "uart1clk-gate", SCU1_CLK_UART1, 543 SCU1_CLK_STOP, 12, CLK_IS_CRITICAL), 544 GATE_CLK(SCU1_CLK_GATE_UART2CLK, CLK_GATE_ASPEED, "uart2clk-gate", SCU1_CLK_UART2, 545 SCU1_CLK_STOP, 13, CLK_IS_CRITICAL), 546 GATE_CLK(SCU1_CLK_GATE_UART3CLK, CLK_GATE_ASPEED, "uart3clk-gate", SCU1_CLK_UART3, 547 SCU1_CLK_STOP, 14, CLK_IS_CRITICAL), 548 GATE_CLK(SCU1_CLK_GATE_I2CCLK, CLK_GATE_ASPEED, "i2cclk-gate", -1, SCU1_CLK_STOP, 15, 0), 549 GATE_CLK(SCU1_CLK_GATE_I3C0CLK, CLK_GATE_ASPEED, "i3c0clk-gate", SCU1_CLK_I3C, 550 SCU1_CLK_STOP, 16, 0), 551 GATE_CLK(SCU1_CLK_GATE_I3C1CLK, CLK_GATE_ASPEED, "i3c1clk-gate", SCU1_CLK_I3C, 552 SCU1_CLK_STOP, 17, 0), 553 GATE_CLK(SCU1_CLK_GATE_I3C2CLK, CLK_GATE_ASPEED, "i3c2clk-gate", SCU1_CLK_I3C, 554 SCU1_CLK_STOP, 18, 0), 555 GATE_CLK(SCU1_CLK_GATE_I3C3CLK, CLK_GATE_ASPEED, "i3c3clk-gate", SCU1_CLK_I3C, 556 SCU1_CLK_STOP, 19, 0), 557 GATE_CLK(SCU1_CLK_GATE_I3C4CLK, CLK_GATE_ASPEED, "i3c4clk-gate", SCU1_CLK_I3C, 558 SCU1_CLK_STOP, 20, 0), 559 GATE_CLK(SCU1_CLK_GATE_I3C5CLK, CLK_GATE_ASPEED, "i3c5clk-gate", SCU1_CLK_I3C, 560 SCU1_CLK_STOP, 21, 0), 561 GATE_CLK(SCU1_CLK_GATE_I3C6CLK, CLK_GATE_ASPEED, "i3c6clk-gate", SCU1_CLK_I3C, 562 SCU1_CLK_STOP, 22, 0), 563 GATE_CLK(SCU1_CLK_GATE_I3C7CLK, CLK_GATE_ASPEED, "i3c7clk-gate", SCU1_CLK_I3C, 564 SCU1_CLK_STOP, 23, 0), 565 GATE_CLK(SCU1_CLK_GATE_I3C8CLK, CLK_GATE_ASPEED, "i3c8clk-gate", SCU1_CLK_I3C, 566 SCU1_CLK_STOP, 24, 0), 567 GATE_CLK(SCU1_CLK_GATE_I3C9CLK, CLK_GATE_ASPEED, "i3c9clk-gate", SCU1_CLK_I3C, 568 SCU1_CLK_STOP, 25, 0), 569 GATE_CLK(SCU1_CLK_GATE_I3C10CLK, CLK_GATE_ASPEED, "i3c10clk-gate", SCU1_CLK_I3C, 570 SCU1_CLK_STOP, 26, 0), 571 GATE_CLK(SCU1_CLK_GATE_I3C11CLK, CLK_GATE_ASPEED, "i3c11clk-gate", SCU1_CLK_I3C, 572 SCU1_CLK_STOP, 27, 0), 573 GATE_CLK(SCU1_CLK_GATE_I3C12CLK, CLK_GATE_ASPEED, "i3c12clk-gate", SCU1_CLK_I3C, 574 SCU1_CLK_STOP, 28, 0), 575 GATE_CLK(SCU1_CLK_GATE_I3C13CLK, CLK_GATE_ASPEED, "i3c13clk-gate", SCU1_CLK_I3C, 576 SCU1_CLK_STOP, 29, 0), 577 GATE_CLK(SCU1_CLK_GATE_I3C14CLK, CLK_GATE_ASPEED, "i3c14clk-gate", SCU1_CLK_I3C, 578 SCU1_CLK_STOP, 30, 0), 579 GATE_CLK(SCU1_CLK_GATE_I3C15CLK, CLK_GATE_ASPEED, "i3c15clk-gate", SCU1_CLK_I3C, 580 SCU1_CLK_STOP, 31, 0), 581 GATE_CLK(SCU1_CLK_GATE_UART5CLK, CLK_GATE_ASPEED, "uart5clk-gate", SCU1_CLK_UART5, 582 SCU1_CLK_STOP2, 0, CLK_IS_CRITICAL), 583 GATE_CLK(SCU1_CLK_GATE_UART6CLK, CLK_GATE_ASPEED, "uart6clk-gate", SCU1_CLK_UART6, 584 SCU1_CLK_STOP2, 1, CLK_IS_CRITICAL), 585 GATE_CLK(SCU1_CLK_GATE_UART7CLK, CLK_GATE_ASPEED, "uart7clk-gate", SCU1_CLK_UART7, 586 SCU1_CLK_STOP2, 2, CLK_IS_CRITICAL), 587 GATE_CLK(SCU1_CLK_GATE_UART8CLK, CLK_GATE_ASPEED, "uart8clk-gate", SCU1_CLK_UART8, 588 SCU1_CLK_STOP2, 3, CLK_IS_CRITICAL), 589 GATE_CLK(SCU1_CLK_GATE_UART9CLK, CLK_GATE_ASPEED, "uart9clk-gate", SCU1_CLK_UART9, 590 SCU1_CLK_STOP2, 4, 0), 591 GATE_CLK(SCU1_CLK_GATE_UART10CLK, CLK_GATE_ASPEED, "uart10clk-gate", SCU1_CLK_UART10, 592 SCU1_CLK_STOP2, 5, 0), 593 GATE_CLK(SCU1_CLK_GATE_UART11CLK, CLK_GATE_ASPEED, "uart11clk-gate", SCU1_CLK_UART11, 594 SCU1_CLK_STOP2, 6, 0), 595 GATE_CLK(SCU1_CLK_GATE_UART12CLK, CLK_GATE_ASPEED, "uart12clk-gate", SCU1_CLK_UART12, 596 SCU1_CLK_STOP2, 7, 0), 597 GATE_CLK(SCU1_CLK_GATE_FSICLK, CLK_GATE_ASPEED, "fsiclk-gate", -1, SCU1_CLK_STOP2, 8, 0), 598 GATE_CLK(SCU1_CLK_GATE_LTPIPHYCLK, CLK_GATE_ASPEED, "ltpiphyclk-gate", -1, 599 SCU1_CLK_STOP2, 9, 0), 600 GATE_CLK(SCU1_CLK_GATE_LTPICLK, CLK_GATE_ASPEED, "ltpiclk-gate", -1, 601 SCU1_CLK_STOP2, 10, 0), 602 GATE_CLK(SCU1_CLK_GATE_VGALCLK, CLK_GATE_ASPEED, "vgalclk-gate", -1, 603 SCU1_CLK_STOP2, 11, CLK_IS_CRITICAL), 604 GATE_CLK(SCU1_CLK_GATE_UHCICLK, CLK_GATE_ASPEED, "usbuartclk-gate", -1, 605 SCU1_CLK_STOP2, 12, 0), 606 GATE_CLK(SCU1_CLK_GATE_CANCLK, CLK_GATE_ASPEED, "canclk-gate", SCU1_CLK_CAN, 607 SCU1_CLK_STOP2, 13, 0), 608 GATE_CLK(SCU1_CLK_GATE_PCICLK, CLK_GATE_ASPEED, "pciclk-gate", -1, 609 SCU1_CLK_STOP2, 14, 0), 610 GATE_CLK(SCU1_CLK_GATE_SLICLK, CLK_GATE_ASPEED, "soc1-sliclk-gate", -1, 611 SCU1_CLK_STOP2, 15, CLK_IS_CRITICAL), 612 GATE_CLK(SCU1_CLK_GATE_E2MCLK, CLK_GATE_ASPEED, "soc1-e2m-gate", -1, 613 SCU1_CLK_STOP2, 16, CLK_IS_CRITICAL), 614 GATE_CLK(SCU1_CLK_GATE_PORTCUSB2CLK, CLK_GATE_ASPEED, "portcusb2-gate", -1, 615 SCU1_CLK_STOP2, 17, 0), 616 GATE_CLK(SCU1_CLK_GATE_PORTDUSB2CLK, CLK_GATE_ASPEED, "portdusb2-gate", -1, 617 SCU1_CLK_STOP2, 18, 0), 618 GATE_CLK(SCU1_CLK_GATE_LTPI1TXCLK, CLK_GATE_ASPEED, "ltp1tx-gate", -1, 619 SCU1_CLK_STOP2, 19, 0), 620 }; 621 622 static struct clk_hw *ast2700_clk_hw_register_fixed_display(void __iomem *reg, const char *name, 623 struct ast2700_clk_ctrl *clk_ctrl) 624 { 625 unsigned int mult, div, r, n; 626 u32 xdclk; 627 u32 val; 628 629 val = readl(clk_ctrl->base + SCU0_CLK_SEL2); 630 if (val & BIT(29)) 631 xdclk = 800 * HZ_PER_MHZ; 632 else 633 xdclk = 1000 * HZ_PER_MHZ; 634 635 val = readl(reg); 636 r = val & GENMASK(15, 0); 637 n = (val >> 16) & GENMASK(15, 0); 638 mult = r; 639 div = 2 * n; 640 641 return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL, 0, (xdclk * mult) / div); 642 } 643 644 static struct clk_hw *ast2700_clk_hw_register_hpll(void __iomem *reg, 645 const char *name, const struct clk_hw *parent_hw, 646 struct ast2700_clk_ctrl *clk_ctrl) 647 { 648 unsigned int mult, div; 649 u32 val; 650 651 val = readl(clk_ctrl->base + SCU0_HWSTRAP1); 652 if ((readl(clk_ctrl->base) & REVISION_ID) && (val & BIT(3))) { 653 switch ((val & GENMASK(4, 2)) >> 2) { 654 case 2: 655 return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL, 656 0, 1800 * HZ_PER_MHZ); 657 case 3: 658 return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL, 659 0, 1700 * HZ_PER_MHZ); 660 case 6: 661 return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL, 662 0, 1200 * HZ_PER_MHZ); 663 case 7: 664 return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL, 665 0, 800 * HZ_PER_MHZ); 666 default: 667 return ERR_PTR(-EINVAL); 668 } 669 } else if ((val & GENMASK(3, 2)) != 0) { 670 switch ((val & GENMASK(3, 2)) >> 2) { 671 case 1: 672 return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL, 673 0, 1900 * HZ_PER_MHZ); 674 case 2: 675 return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL, 676 0, 1800 * HZ_PER_MHZ); 677 case 3: 678 return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL, 679 0, 1700 * HZ_PER_MHZ); 680 default: 681 return ERR_PTR(-EINVAL); 682 } 683 } else { 684 val = readl(reg); 685 686 if (val & BIT(24)) { 687 /* Pass through mode */ 688 mult = 1; 689 div = 1; 690 } else { 691 u32 m = val & 0x1fff; 692 u32 n = (val >> 13) & 0x3f; 693 u32 p = (val >> 19) & 0xf; 694 695 mult = (m + 1) / (2 * (n + 1)); 696 div = p + 1; 697 } 698 } 699 700 return devm_clk_hw_register_fixed_factor_parent_hw(clk_ctrl->dev, name, 701 parent_hw, 0, mult, div); 702 } 703 704 static struct clk_hw *ast2700_clk_hw_register_pll(int clk_idx, void __iomem *reg, 705 const char *name, const struct clk_hw *parent_hw, 706 struct ast2700_clk_ctrl *clk_ctrl) 707 { 708 int scu = clk_ctrl->clk_data->scu; 709 unsigned int mult, div; 710 u32 val = readl(reg); 711 712 if (val & BIT(24)) { 713 /* Pass through mode */ 714 mult = 1; 715 div = 1; 716 } else { 717 u32 m = val & 0x1fff; 718 u32 n = (val >> 13) & 0x3f; 719 u32 p = (val >> 19) & 0xf; 720 721 if (scu) { 722 mult = (m + 1) / (n + 1); 723 div = p + 1; 724 } else { 725 if (clk_idx == SCU0_CLK_MPLL) { 726 mult = m / (n + 1); 727 div = p + 1; 728 } else { 729 mult = (m + 1) / (2 * (n + 1)); 730 div = p + 1; 731 } 732 } 733 } 734 735 return devm_clk_hw_register_fixed_factor_parent_hw(clk_ctrl->dev, name, 736 parent_hw, 0, mult, div); 737 } 738 739 static struct clk_hw *ast2700_clk_hw_register_uartpll(void __iomem *reg, const char *name, 740 const struct clk_hw *parent_hw, 741 struct ast2700_clk_ctrl *clk_ctrl) 742 { 743 unsigned int mult, div; 744 u32 val = readl(reg); 745 u32 r = val & 0xff; 746 u32 n = (val >> 8) & 0x3ff; 747 748 mult = r; 749 div = n * 2; 750 751 return devm_clk_hw_register_fixed_factor_parent_hw(clk_ctrl->dev, name, 752 parent_hw, 0, mult, div); 753 } 754 755 static struct clk_hw *ast2700_clk_hw_register_misc(int clk_idx, void __iomem *reg, 756 const char *name, const struct clk_hw *parent_hw, 757 struct ast2700_clk_ctrl *clk_ctrl) 758 { 759 u32 div = 0; 760 761 if (clk_idx == SCU0_CLK_MPHY) { 762 div = readl(reg) + 1; 763 } else if (clk_idx == SCU0_CLK_U2PHY_REFCLK) { 764 if (readl(clk_ctrl->base) & REVISION_ID) 765 div = (GET_USB_REFCLK_DIV(readl(reg)) + 1) << 4; 766 else 767 div = (GET_USB_REFCLK_DIV(readl(reg)) + 1) << 1; 768 } else { 769 return ERR_PTR(-EINVAL); 770 } 771 772 return devm_clk_hw_register_fixed_factor_parent_hw(clk_ctrl->dev, name, 773 parent_hw, 0, 1, div); 774 } 775 776 static int ast2700_clk_is_enabled(struct clk_hw *hw) 777 { 778 struct clk_gate *gate = to_clk_gate(hw); 779 u32 clk = BIT(gate->bit_idx); 780 u32 reg; 781 782 reg = readl(gate->reg); 783 784 return !(reg & clk); 785 } 786 787 static int ast2700_clk_enable(struct clk_hw *hw) 788 { 789 struct clk_gate *gate = to_clk_gate(hw); 790 u32 clk = BIT(gate->bit_idx); 791 792 if (readl(gate->reg) & clk) 793 writel(clk, gate->reg + 0x04); 794 795 return 0; 796 } 797 798 static void ast2700_clk_disable(struct clk_hw *hw) 799 { 800 struct clk_gate *gate = to_clk_gate(hw); 801 u32 clk = BIT(gate->bit_idx); 802 803 /* Clock is set to enable, so use write to set register */ 804 writel(clk, gate->reg); 805 } 806 807 static const struct clk_ops ast2700_clk_gate_ops = { 808 .enable = ast2700_clk_enable, 809 .disable = ast2700_clk_disable, 810 .is_enabled = ast2700_clk_is_enabled, 811 }; 812 813 static struct clk_hw *ast2700_clk_hw_register_gate(struct device *dev, const char *name, 814 const struct clk_hw *parent_hw, 815 void __iomem *reg, u8 clock_idx, 816 unsigned long flags, spinlock_t *lock) 817 { 818 struct clk_init_data init; 819 struct clk_gate *gate; 820 struct clk_hw *hw; 821 int ret = -EINVAL; 822 823 gate = kzalloc_obj(*gate); 824 if (!gate) 825 return ERR_PTR(-ENOMEM); 826 827 init.name = name; 828 init.ops = &ast2700_clk_gate_ops; 829 init.flags = flags; 830 init.parent_names = NULL; 831 init.parent_hws = parent_hw ? &parent_hw : NULL; 832 init.parent_data = NULL; 833 init.num_parents = parent_hw ? 1 : 0; 834 835 gate->reg = reg; 836 gate->bit_idx = clock_idx; 837 gate->flags = 0; 838 gate->lock = lock; 839 gate->hw.init = &init; 840 841 hw = &gate->hw; 842 ret = clk_hw_register(dev, hw); 843 if (ret) { 844 kfree(gate); 845 hw = ERR_PTR(ret); 846 } 847 848 return hw; 849 } 850 851 static void ast2700_soc1_configure_i3c_clk(struct ast2700_clk_ctrl *clk_ctrl) 852 { 853 if (readl(clk_ctrl->base) & REVISION_ID) { 854 u32 val; 855 856 /* I3C 250MHz = HPLL/4 */ 857 val = readl(clk_ctrl->base + SCU1_CLK_SEL2) & ~SCU1_CLK_I3C_DIV_MASK; 858 val |= FIELD_PREP(SCU1_CLK_I3C_DIV_MASK, SCU1_CLK_I3C_DIV(4)); 859 writel(val, clk_ctrl->base + SCU1_CLK_SEL2); 860 } 861 } 862 863 static inline const struct clk_hw *get_parent_hw_or_null(struct clk_hw **hws, int idx) 864 { 865 if (idx < 0) 866 return NULL; 867 else 868 return hws[idx]; 869 } 870 871 static int ast2700_soc_clk_probe(struct platform_device *pdev) 872 { 873 const struct ast2700_clk_data *clk_data; 874 struct clk_hw_onecell_data *clk_hw_data; 875 struct ast2700_clk_ctrl *clk_ctrl; 876 struct device *dev = &pdev->dev; 877 struct auxiliary_device *adev; 878 void __iomem *clk_base; 879 struct clk_hw **hws; 880 char *reset_name; 881 int ret; 882 int i; 883 884 clk_ctrl = devm_kzalloc(dev, sizeof(*clk_ctrl), GFP_KERNEL); 885 if (!clk_ctrl) 886 return -ENOMEM; 887 clk_ctrl->dev = dev; 888 dev_set_drvdata(&pdev->dev, clk_ctrl); 889 890 spin_lock_init(&clk_ctrl->lock); 891 892 clk_base = devm_platform_ioremap_resource(pdev, 0); 893 if (IS_ERR(clk_base)) 894 return PTR_ERR(clk_base); 895 896 clk_ctrl->base = clk_base; 897 898 clk_data = device_get_match_data(dev); 899 if (!clk_data) 900 return -ENODEV; 901 902 clk_ctrl->clk_data = clk_data; 903 reset_name = devm_kasprintf(dev, GFP_KERNEL, "reset%d", clk_data->scu); 904 905 clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws, clk_data->nr_clks), 906 GFP_KERNEL); 907 if (!clk_hw_data) 908 return -ENOMEM; 909 910 clk_hw_data->num = clk_data->nr_clks; 911 hws = clk_hw_data->hws; 912 913 if (clk_data->scu) 914 ast2700_soc1_configure_i3c_clk(clk_ctrl); 915 916 for (i = 0; i < clk_data->nr_clks; i++) { 917 const struct ast2700_clk_info *clk = &clk_data->clk_info[i]; 918 const struct clk_hw *phw = NULL; 919 unsigned int id = clk->id; 920 void __iomem *reg = NULL; 921 922 if (id >= clk_hw_data->num || hws[id]) { 923 dev_err(dev, "clk id %u invalid for %s\n", id, clk->name); 924 return -EINVAL; 925 } 926 927 if (clk->type == CLK_FIXED) { 928 const struct ast2700_clk_fixed_rate_data *fixed_rate = &clk->data.rate; 929 930 hws[id] = devm_clk_hw_register_fixed_rate(dev, clk->name, NULL, 0, 931 fixed_rate->fixed_rate); 932 } else if (clk->type == CLK_FIXED_FACTOR) { 933 const struct ast2700_clk_fixed_factor_data *factor = &clk->data.factor; 934 935 phw = hws[factor->parent_id]; 936 hws[id] = devm_clk_hw_register_fixed_factor_parent_hw(dev, clk->name, 937 phw, 0, factor->mult, 938 factor->div); 939 } else if (clk->type == CLK_FIXED_DISPLAY) { 940 reg = clk_ctrl->base + clk->data.display_rate.reg; 941 942 hws[id] = ast2700_clk_hw_register_fixed_display(reg, clk->name, clk_ctrl); 943 } else if (clk->type == CLK_HPLL) { 944 const struct ast2700_clk_pll_data *pll = &clk->data.pll; 945 946 reg = clk_ctrl->base + pll->reg; 947 phw = hws[pll->parent_id]; 948 hws[id] = ast2700_clk_hw_register_hpll(reg, clk->name, phw, clk_ctrl); 949 } else if (clk->type == CLK_PLL) { 950 const struct ast2700_clk_pll_data *pll = &clk->data.pll; 951 952 reg = clk_ctrl->base + pll->reg; 953 phw = hws[pll->parent_id]; 954 hws[id] = ast2700_clk_hw_register_pll(id, reg, clk->name, phw, clk_ctrl); 955 } else if (clk->type == CLK_UART_PLL) { 956 const struct ast2700_clk_pll_data *pll = &clk->data.pll; 957 958 reg = clk_ctrl->base + pll->reg; 959 phw = hws[pll->parent_id]; 960 hws[id] = ast2700_clk_hw_register_uartpll(reg, clk->name, phw, clk_ctrl); 961 } else if (clk->type == CLK_MUX) { 962 const struct ast2700_clk_mux_data *mux = &clk->data.mux; 963 964 reg = clk_ctrl->base + mux->reg; 965 for (int j = 0; j < mux->num_parents; j++) { 966 unsigned int pid = mux->parent_ids[j]; 967 968 mux->parent_hws[j] = hws[pid]; 969 } 970 971 hws[id] = devm_clk_hw_register_mux_parent_hws(dev, clk->name, 972 mux->parent_hws, 973 mux->num_parents, 0, 974 reg, mux->bit_shift, 975 mux->bit_width, 0, 976 &clk_ctrl->lock); 977 } else if (clk->type == CLK_MISC) { 978 const struct ast2700_clk_pll_data *pll = &clk->data.pll; 979 980 reg = clk_ctrl->base + pll->reg; 981 phw = hws[pll->parent_id]; 982 hws[id] = ast2700_clk_hw_register_misc(id, reg, clk->name, phw, clk_ctrl); 983 } else if (clk->type == CLK_DIVIDER) { 984 const struct ast2700_clk_div_data *divider = &clk->data.div; 985 986 reg = clk_ctrl->base + divider->reg; 987 phw = hws[divider->parent_id]; 988 hws[id] = clk_hw_register_divider_table_parent_hw(dev, clk->name, 989 phw, 990 0, reg, 991 divider->bit_shift, 992 divider->bit_width, 0, 993 divider->div_table, 994 &clk_ctrl->lock); 995 } else if (clk->type == CLK_GATE_ASPEED) { 996 const struct ast2700_clk_gate_data *gate = &clk->data.gate; 997 998 phw = get_parent_hw_or_null(hws, gate->parent_id); 999 reg = clk_ctrl->base + gate->reg; 1000 hws[id] = ast2700_clk_hw_register_gate(dev, clk->name, phw, reg, gate->bit, 1001 gate->flags, &clk_ctrl->lock); 1002 } else { 1003 const struct ast2700_clk_gate_data *gate = &clk->data.gate; 1004 1005 phw = get_parent_hw_or_null(hws, gate->parent_id); 1006 reg = clk_ctrl->base + gate->reg; 1007 hws[id] = devm_clk_hw_register_gate_parent_hw(dev, clk->name, phw, 1008 gate->flags, reg, gate->bit, 1009 0, &clk_ctrl->lock); 1010 } 1011 1012 if (IS_ERR(hws[id])) 1013 return PTR_ERR(hws[id]); 1014 } 1015 1016 ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_hw_data); 1017 if (ret) 1018 return ret; 1019 1020 adev = devm_auxiliary_device_create(dev, reset_name, (__force void *)clk_base); 1021 if (!adev) 1022 return -ENODEV; 1023 1024 return 0; 1025 } 1026 1027 static const struct ast2700_clk_data ast2700_clk0_data = { 1028 .scu = 0, 1029 .nr_clks = ARRAY_SIZE(ast2700_scu0_clk_info), 1030 .clk_info = ast2700_scu0_clk_info, 1031 }; 1032 1033 static const struct ast2700_clk_data ast2700_clk1_data = { 1034 .scu = 1, 1035 .nr_clks = ARRAY_SIZE(ast2700_scu1_clk_info), 1036 .clk_info = ast2700_scu1_clk_info, 1037 }; 1038 1039 static const struct of_device_id ast2700_scu_match[] = { 1040 { .compatible = "aspeed,ast2700-scu0", .data = &ast2700_clk0_data }, 1041 { .compatible = "aspeed,ast2700-scu1", .data = &ast2700_clk1_data }, 1042 { /* sentinel */ } 1043 }; 1044 1045 MODULE_DEVICE_TABLE(of, ast2700_scu_match); 1046 1047 static struct platform_driver ast2700_scu_driver = { 1048 .probe = ast2700_soc_clk_probe, 1049 .driver = { 1050 .name = "clk-ast2700", 1051 .of_match_table = ast2700_scu_match, 1052 }, 1053 }; 1054 1055 module_platform_driver(ast2700_scu_driver); 1056