Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clk: socfpga: agilex5: add clock driver for Agilex5

Add the new Clock manager driver to support new Agilex5 platform. The new
driver got rid of the clk_parent_data structures as there are no 'clock-names'
property in the DT bindings and use parent_names internally. This is based on
the previous feedback from the maintainer.

Signed-off-by: Ang Tien Sung <tiensung.ang@altera.com>
Signed-off-by: Khairul Anuar Romli <khairul.anuar.romli@altera.com>
Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>

authored by

Khairul Anuar Romli and committed by
Dinh Nguyen
2050b57e 3a866087

+736 -2
+1 -1
drivers/clk/socfpga/Kconfig
··· 13 13 default ARM && ARCH_INTEL_SOCFPGA 14 14 15 15 config CLK_INTEL_SOCFPGA64 16 - bool "Intel Stratix / Agilex / N5X clock controller support" if COMPILE_TEST && (!ARM64 || !ARCH_INTEL_SOCFPGA) 16 + bool "Intel Stratix / Agilex / N5X / Agilex5 clock controller support" if COMPILE_TEST && (!ARM64 || !ARCH_INTEL_SOCFPGA) 17 17 default ARM64 && ARCH_INTEL_SOCFPGA 18 18 19 19 endif # CLK_INTEL_SOCFPGA
+1 -1
drivers/clk/socfpga/Makefile
··· 3 3 clk-pll-a10.o clk-periph-a10.o clk-gate-a10.o 4 4 obj-$(CONFIG_CLK_INTEL_SOCFPGA64) += clk-s10.o \ 5 5 clk-pll-s10.o clk-periph-s10.o clk-gate-s10.o \ 6 - clk-agilex.o 6 + clk-agilex.o clk-agilex5.o
+561
drivers/clk/socfpga/clk-agilex5.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (C) 2022-2024, Intel Corporation 4 + * Copyright (C) 2025, Altera Corporation 5 + */ 6 + #include <linux/slab.h> 7 + #include <linux/clk-provider.h> 8 + #include <linux/of.h> 9 + #include <linux/platform_device.h> 10 + #include <dt-bindings/clock/intel,agilex5-clkmgr.h> 11 + #include "stratix10-clk.h" 12 + #include "clk.h" 13 + 14 + /* External parent clocks come from DT via fw_name */ 15 + static const char * const boot_pll_parents[] = { 16 + "osc1", 17 + "cb-intosc-hs-div2-clk", 18 + }; 19 + 20 + static const char * const main_pll_parents[] = { 21 + "osc1", 22 + "cb-intosc-hs-div2-clk", 23 + "f2s-free-clk", 24 + }; 25 + 26 + static const char * const periph_pll_parents[] = { 27 + "osc1", 28 + "cb-intosc-hs-div2-clk", 29 + }; 30 + 31 + /* Core free muxes */ 32 + static const char * const core0_free_mux[] = { 33 + "main_pll_c1", 34 + "peri_pll_c0", 35 + "osc1", 36 + "cb-intosc-hs-div2-clk", 37 + "f2s-free-clk", 38 + }; 39 + 40 + static const char * const core1_free_mux[] = { 41 + "main_pll_c1", 42 + "peri_pll_c0", 43 + "osc1", 44 + "cb-intosc-hs-div2-clk", 45 + "f2s-free-clk", 46 + }; 47 + 48 + static const char * const core2_free_mux[] = { 49 + "main_pll_c0", 50 + "osc1", 51 + "cb-intosc-hs-div2-clk", 52 + "f2s-free-clk", 53 + }; 54 + 55 + static const char * const core3_free_mux[] = { 56 + "main_pll_c0", 57 + "osc1", 58 + "cb-intosc-hs-div2-clk", 59 + "f2s-free-clk", 60 + }; 61 + 62 + static const char * const dsu_free_mux[] = { 63 + "main_pll_c2", 64 + "peri_pll_c0", 65 + "osc1", 66 + "cb-intosc-hs-div2-clk", 67 + "f2s-free-clk", 68 + }; 69 + 70 + static const char * const noc_free_mux[] = { 71 + "main_pll_c3", 72 + "peri_pll_c1", 73 + "osc1", 74 + "cb-intosc-hs-div2-clk", 75 + "f2s-free-clk", 76 + }; 77 + 78 + static const char * const emac_ptp_free_mux[] = { 79 + "main_pll_c3", 80 + "peri_pll_c3", 81 + "osc1", 82 + "cb-intosc-hs-div2-clk", 83 + "f2s-free-clk", 84 + }; 85 + 86 + static const char * const emaca_free_mux[] = { 87 + "main_pll_c2", 88 + "peri_pll_c3", 89 + "osc1", 90 + "cb-intosc-hs-div2-clk", 91 + "f2s-free-clk", 92 + }; 93 + 94 + static const char * const emacb_free_mux[] = { 95 + "main_pll_c3", 96 + "peri_pll_c3", 97 + "osc1", 98 + "cb-intosc-hs-div2-clk", 99 + "f2s-free-clk", 100 + }; 101 + 102 + static const char * const gpio_db_free_mux[] = { 103 + "main_pll_c3", 104 + "peri_pll_c1", 105 + "osc1", 106 + "cb-intosc-hs-div2-clk", 107 + "f2s-free-clk", 108 + }; 109 + 110 + static const char * const psi_ref_free_mux[] = { 111 + "main_pll_c1", 112 + "peri_pll_c3", 113 + "osc1", 114 + "cb-intosc-hs-div2-clk", 115 + "f2s-free-clk", 116 + }; 117 + 118 + static const char * const usb31_free_mux[] = { 119 + "main_pll_c3", 120 + "peri_pll_c2", 121 + "osc1", 122 + "cb-intosc-hs-div2-clk", 123 + "f2s-free-clk", 124 + }; 125 + 126 + static const char * const s2f_user0_free_mux[] = { 127 + "main_pll_c1", 128 + "peri_pll_c3", 129 + "osc1", 130 + "cb-intosc-hs-div2-clk", 131 + "f2s-free-clk", 132 + }; 133 + 134 + static const char * const s2f_user1_free_mux[] = { 135 + "main_pll_c1", 136 + "peri_pll_c3", 137 + "osc1", 138 + "cb-intosc-hs-div2-clk", 139 + "f2s-free-clk", 140 + }; 141 + 142 + /* Secondary muxes between free_clk and boot_clk */ 143 + static const char * const core0_mux[] = { 144 + "core0_free_clk", 145 + "boot_clk", 146 + }; 147 + 148 + static const char * const core1_mux[] = { 149 + "core1_free_clk", 150 + "boot_clk", 151 + }; 152 + 153 + static const char * const core2_mux[] = { 154 + "core2_free_clk", 155 + "boot_clk", 156 + }; 157 + 158 + static const char * const core3_mux[] = { 159 + "core3_free_clk", 160 + "boot_clk", 161 + }; 162 + 163 + static const char * const dsu_mux[] = { 164 + "dsu_free_clk", 165 + "boot_clk", 166 + }; 167 + 168 + static const char * const noc_mux[] = { 169 + "noc_free_clk", 170 + "boot_clk", 171 + }; 172 + 173 + static const char * const emac_mux[] = { 174 + "emaca_free_clk", 175 + "emacb_free_clk", 176 + "boot_clk", 177 + }; 178 + 179 + static const char * const s2f_user0_mux[] = { 180 + "s2f_user0_free_clk", 181 + "boot_clk", 182 + }; 183 + 184 + static const char * const s2f_user1_mux[] = { 185 + "s2f_user1_free_clk", 186 + "boot_clk", 187 + }; 188 + 189 + static const char * const psi_mux[] = { 190 + "psi_ref_free_clk", 191 + "boot_clk", 192 + }; 193 + 194 + static const char * const gpio_db_mux[] = { 195 + "gpio_db_free_clk", 196 + "boot_clk", 197 + }; 198 + 199 + static const char * const emac_ptp_mux[] = { 200 + "emac_ptp_free_clk", 201 + "boot_clk", 202 + }; 203 + 204 + static const char * const usb31_mux[] = { 205 + "usb31_free_clk", 206 + "boot_clk", 207 + }; 208 + 209 + static const struct agilex5_pll_clock agilex5_pll_clks[] = { 210 + { 211 + .id = AGILEX5_BOOT_CLK, 212 + .name = "boot_clk", 213 + .parent_names = boot_pll_parents, 214 + .num_parents = ARRAY_SIZE(boot_pll_parents), 215 + .flags = 0, 216 + .offset = 0x0, 217 + }, 218 + { 219 + .id = AGILEX5_MAIN_PLL_CLK, 220 + .name = "main_pll", 221 + .parent_names = main_pll_parents, 222 + .num_parents = ARRAY_SIZE(main_pll_parents), 223 + .flags = 0, 224 + .offset = 0x48, 225 + }, 226 + { 227 + .id = AGILEX5_PERIPH_PLL_CLK, 228 + .name = "periph_pll", 229 + .parent_names = periph_pll_parents, 230 + .num_parents = ARRAY_SIZE(periph_pll_parents), 231 + .flags = 0, 232 + .offset = 0x9C, 233 + }, 234 + }; 235 + 236 + /* Main PLL C0, C1, C2, C3 and Peri PLL C0, C1, C2, C3. With ping-pong counter. */ 237 + static const struct stratix10_perip_c_clock agilex5_main_perip_c_clks[] = { 238 + { AGILEX5_MAIN_PLL_C0_CLK, "main_pll_c0", "main_pll", NULL, 1, 0, 239 + 0x5C }, 240 + { AGILEX5_MAIN_PLL_C1_CLK, "main_pll_c1", "main_pll", NULL, 1, 0, 241 + 0x60 }, 242 + { AGILEX5_MAIN_PLL_C2_CLK, "main_pll_c2", "main_pll", NULL, 1, 0, 243 + 0x64 }, 244 + { AGILEX5_MAIN_PLL_C3_CLK, "main_pll_c3", "main_pll", NULL, 1, 0, 245 + 0x68 }, 246 + { AGILEX5_PERIPH_PLL_C0_CLK, "peri_pll_c0", "periph_pll", NULL, 1, 0, 247 + 0xB0 }, 248 + { AGILEX5_PERIPH_PLL_C1_CLK, "peri_pll_c1", "periph_pll", NULL, 1, 0, 249 + 0xB4 }, 250 + { AGILEX5_PERIPH_PLL_C2_CLK, "peri_pll_c2", "periph_pll", NULL, 1, 0, 251 + 0xB8 }, 252 + { AGILEX5_PERIPH_PLL_C3_CLK, "peri_pll_c3", "periph_pll", NULL, 1, 0, 253 + 0xBC }, 254 + }; 255 + 256 + /* Non-SW clock-gated enabled clocks */ 257 + static const struct agilex5_perip_cnt_clock agilex5_main_perip_cnt_clks[] = { 258 + { AGILEX5_CORE0_FREE_CLK, "core0_free_clk", core0_free_mux, 259 + ARRAY_SIZE(core0_free_mux), 0, 0x0100, 0, 0, 0}, 260 + { AGILEX5_CORE1_FREE_CLK, "core1_free_clk", core1_free_mux, 261 + ARRAY_SIZE(core1_free_mux), 0, 0x0104, 0, 0, 0}, 262 + { AGILEX5_CORE2_FREE_CLK, "core2_free_clk", core2_free_mux, 263 + ARRAY_SIZE(core2_free_mux), 0, 0x010C, 0, 0, 0}, 264 + { AGILEX5_CORE3_FREE_CLK, "core3_free_clk", core3_free_mux, 265 + ARRAY_SIZE(core3_free_mux), 0, 0x0110, 0, 0, 0}, 266 + { AGILEX5_DSU_FREE_CLK, "dsu_free_clk", dsu_free_mux, 267 + ARRAY_SIZE(dsu_free_mux), 0, 0xfc, 0, 0, 0}, 268 + { AGILEX5_NOC_FREE_CLK, "noc_free_clk", noc_free_mux, 269 + ARRAY_SIZE(noc_free_mux), 0, 0x40, 0, 0, 0 }, 270 + { AGILEX5_EMAC_A_FREE_CLK, "emaca_free_clk", emaca_free_mux, 271 + ARRAY_SIZE(emaca_free_mux), 0, 0xD4, 0, 0x88, 0 }, 272 + { AGILEX5_EMAC_B_FREE_CLK, "emacb_free_clk", emacb_free_mux, 273 + ARRAY_SIZE(emacb_free_mux), 0, 0xD8, 0, 0x88, 1 }, 274 + { AGILEX5_EMAC_PTP_FREE_CLK, "emac_ptp_free_clk", emac_ptp_free_mux, 275 + ARRAY_SIZE(emac_ptp_free_mux), 0, 0xDC, 0, 0x88, 2 }, 276 + { AGILEX5_GPIO_DB_FREE_CLK, "gpio_db_free_clk", gpio_db_free_mux, 277 + ARRAY_SIZE(gpio_db_free_mux), 0, 0xE0, 0, 0x88, 3 }, 278 + { AGILEX5_S2F_USER0_FREE_CLK, "s2f_user0_free_clk", s2f_user0_free_mux, 279 + ARRAY_SIZE(s2f_user0_free_mux), 0, 0xE8, 0, 0x30, 2 }, 280 + { AGILEX5_S2F_USER1_FREE_CLK, "s2f_user1_free_clk", s2f_user1_free_mux, 281 + ARRAY_SIZE(s2f_user1_free_mux), 0, 0xEC, 0, 0x88, 5 }, 282 + { AGILEX5_PSI_REF_FREE_CLK, "psi_ref_free_clk", psi_ref_free_mux, 283 + ARRAY_SIZE(psi_ref_free_mux), 0, 0xF0, 0, 0x88, 6 }, 284 + { AGILEX5_USB31_FREE_CLK, "usb31_free_clk", usb31_free_mux, 285 + ARRAY_SIZE(usb31_free_mux), 0, 0xF8, 0, 0x88, 7}, 286 + }; 287 + 288 + static const char * const cs_pdbg_parents[] = { "cs_at_clk" }; 289 + static const char * const usb31_bus_clk_early_parents[] = { "l4_main_clk" }; 290 + static const char * const l4_mp_clk_parent[] = { "l4_mp_clk" }; 291 + static const char * const l4_sp_clk_parent[] = { "l4_sp_clk" }; 292 + static const char * const dfi_clk_parent[] = { "dfi_clk" }; 293 + 294 + /* SW Clock gate enabled clocks */ 295 + static const struct agilex5_gate_clock agilex5_gate_clks[] = { 296 + { AGILEX5_CORE0_CLK, "core0_clk", core0_mux, 297 + ARRAY_SIZE(core0_mux), 0, 0x24, 8, 0, 0, 0, 0x30, 5, 0 }, 298 + { AGILEX5_CORE1_CLK, "core1_clk", core1_mux, 299 + ARRAY_SIZE(core1_mux), 0, 0x24, 9, 0, 0, 0, 0x30, 5, 0 }, 300 + { AGILEX5_CORE2_CLK, "core2_clk", core2_mux, 301 + ARRAY_SIZE(core2_mux), 0, 0x24, 10, 0, 0, 0, 0x30, 6, 0 }, 302 + { AGILEX5_CORE3_CLK, "core3_clk", core3_mux, 303 + ARRAY_SIZE(core3_mux), 0, 0x24, 11, 0, 0, 0, 0x30, 7, 0 }, 304 + { AGILEX5_MPU_CLK, "dsu_clk", dsu_mux, ARRAY_SIZE(dsu_mux), 0, 0, 0, 305 + 0, 0, 0, 0x34, 4, 0 }, 306 + { AGILEX5_MPU_PERIPH_CLK, "mpu_periph_clk", dsu_mux, 307 + ARRAY_SIZE(dsu_mux), 0, 0, 0, 0x44, 20, 2, 0x34, 4, 0 }, 308 + { AGILEX5_MPU_CCU_CLK, "mpu_ccu_clk", dsu_mux, 309 + ARRAY_SIZE(dsu_mux), 0, 0, 0, 0x44, 18, 2, 0x34, 4, 0 }, 310 + { AGILEX5_L4_MAIN_CLK, "l4_main_clk", noc_mux, ARRAY_SIZE(noc_mux), 311 + CLK_IS_CRITICAL, 0x24, 1, 0, 0, 0, 0, 0, 0 }, 312 + { AGILEX5_L4_MP_CLK, "l4_mp_clk", noc_mux, ARRAY_SIZE(noc_mux), 0, 313 + 0x24, 2, 0x44, 4, 2, 0x30, 1, 0 }, 314 + { AGILEX5_L4_SYS_FREE_CLK, "l4_sys_free_clk", noc_mux, 315 + ARRAY_SIZE(noc_mux), 0, 0, 0, 0x44, 2, 2, 0x30, 1, 0 }, 316 + { AGILEX5_L4_SP_CLK, "l4_sp_clk", noc_mux, ARRAY_SIZE(noc_mux), 317 + CLK_IS_CRITICAL, 0x24, 3, 0x44, 6, 2, 0x30, 1, 0 }, 318 + 319 + /* Core sight clocks*/ 320 + { AGILEX5_CS_AT_CLK, "cs_at_clk", noc_mux, ARRAY_SIZE(noc_mux), 0, 321 + 0x24, 4, 0x44, 24, 2, 0x30, 1, 0 }, 322 + { AGILEX5_CS_TRACE_CLK, "cs_trace_clk", noc_mux, 323 + ARRAY_SIZE(noc_mux), 0, 0x24, 4, 0x44, 26, 2, 0x30, 1, 0 }, 324 + { AGILEX5_CS_PDBG_CLK, "cs_pdbg_clk", cs_pdbg_parents, 1, 0, 0x24, 4, 325 + 0x44, 28, 1, 0, 0, 0 }, 326 + 327 + /* Main Peripheral PLL1 Begin */ 328 + { AGILEX5_EMAC0_CLK, "emac0_clk", emac_mux, ARRAY_SIZE(emac_mux), 329 + 0, 0x7C, 0, 0, 0, 0, 0x94, 26, 0 }, 330 + { AGILEX5_EMAC1_CLK, "emac1_clk", emac_mux, ARRAY_SIZE(emac_mux), 331 + 0, 0x7C, 1, 0, 0, 0, 0x94, 27, 0 }, 332 + { AGILEX5_EMAC2_CLK, "emac2_clk", emac_mux, ARRAY_SIZE(emac_mux), 333 + 0, 0x7C, 2, 0, 0, 0, 0x94, 28, 0 }, 334 + { AGILEX5_EMAC_PTP_CLK, "emac_ptp_clk", emac_ptp_mux, 335 + ARRAY_SIZE(emac_ptp_mux), 0, 0x7C, 3, 0, 0, 0, 0x88, 2, 0 }, 336 + { AGILEX5_GPIO_DB_CLK, "gpio_db_clk", gpio_db_mux, 337 + ARRAY_SIZE(gpio_db_mux), 0, 0x7C, 4, 0x98, 0, 16, 0x88, 3, 1 }, 338 + /* Main Peripheral PLL1 End */ 339 + 340 + /* Peripheral clocks */ 341 + { AGILEX5_S2F_USER0_CLK, "s2f_user0_clk", s2f_user0_mux, 342 + ARRAY_SIZE(s2f_user0_mux), 0, 0x24, 6, 0, 0, 0, 0x30, 2, 0 }, 343 + { AGILEX5_S2F_USER1_CLK, "s2f_user1_clk", s2f_user1_mux, 344 + ARRAY_SIZE(s2f_user1_mux), 0, 0x7C, 6, 0, 0, 0, 0x88, 5, 0 }, 345 + { AGILEX5_PSI_REF_CLK, "psi_ref_clk", psi_mux, 346 + ARRAY_SIZE(psi_mux), 0, 0x7C, 7, 0, 0, 0, 0x88, 6, 0 }, 347 + { AGILEX5_USB31_SUSPEND_CLK, "usb31_suspend_clk", usb31_mux, 348 + ARRAY_SIZE(usb31_mux), 0, 0x7C, 25, 0, 0, 0, 0x88, 7, 0 }, 349 + { AGILEX5_USB31_BUS_CLK_EARLY, "usb31_bus_clk_early", usb31_bus_clk_early_parents, 350 + 1, 0, 0x7C, 25, 0, 0, 0, 0, 0, 0 }, 351 + { AGILEX5_USB2OTG_HCLK, "usb2otg_hclk", l4_mp_clk_parent, 1, 0, 0x7C, 352 + 8, 0, 0, 0, 0, 0, 0 }, 353 + { AGILEX5_SPIM_0_CLK, "spim_0_clk", l4_mp_clk_parent, 1, 0, 0x7C, 9, 354 + 0, 0, 0, 0, 0, 0 }, 355 + { AGILEX5_SPIM_1_CLK, "spim_1_clk", l4_mp_clk_parent, 1, 0, 0x7C, 11, 356 + 0, 0, 0, 0, 0, 0 }, 357 + { AGILEX5_SPIS_0_CLK, "spis_0_clk", l4_sp_clk_parent, 1, 0, 0x7C, 12, 358 + 0, 0, 0, 0, 0, 0 }, 359 + { AGILEX5_SPIS_1_CLK, "spis_1_clk", l4_sp_clk_parent, 1, 0, 0x7C, 13, 360 + 0, 0, 0, 0, 0, 0 }, 361 + { AGILEX5_DMA_CORE_CLK, "dma_core_clk", l4_mp_clk_parent, 1, 0, 0x7C, 362 + 14, 0, 0, 0, 0, 0, 0 }, 363 + { AGILEX5_DMA_HS_CLK, "dma_hs_clk", l4_mp_clk_parent, 1, 0, 0x7C, 14, 364 + 0, 0, 0, 0, 0, 0 }, 365 + { AGILEX5_I3C_0_CORE_CLK, "i3c_0_core_clk", l4_mp_clk_parent, 1, 0, 366 + 0x7C, 18, 0, 0, 0, 0, 0, 0 }, 367 + { AGILEX5_I3C_1_CORE_CLK, "i3c_1_core_clk", l4_mp_clk_parent, 1, 0, 368 + 0x7C, 19, 0, 0, 0, 0, 0, 0 }, 369 + { AGILEX5_I2C_0_PCLK, "i2c_0_pclk", l4_sp_clk_parent, 1, 0, 0x7C, 15, 370 + 0, 0, 0, 0, 0, 0 }, 371 + { AGILEX5_I2C_1_PCLK, "i2c_1_pclk", l4_sp_clk_parent, 1, 0, 0x7C, 16, 372 + 0, 0, 0, 0, 0, 0 }, 373 + { AGILEX5_I2C_EMAC0_PCLK, "i2c_emac0_pclk", l4_sp_clk_parent, 1, 0, 374 + 0x7C, 17, 0, 0, 0, 0, 0, 0 }, 375 + { AGILEX5_I2C_EMAC1_PCLK, "i2c_emac1_pclk", l4_sp_clk_parent, 1, 0, 376 + 0x7C, 22, 0, 0, 0, 0, 0, 0 }, 377 + { AGILEX5_I2C_EMAC2_PCLK, "i2c_emac2_pclk", l4_sp_clk_parent, 1, 0, 378 + 0x7C, 27, 0, 0, 0, 0, 0, 0 }, 379 + { AGILEX5_UART_0_PCLK, "uart_0_pclk", l4_sp_clk_parent, 1, 0, 0x7C, 20, 380 + 0, 0, 0, 0, 0, 0 }, 381 + { AGILEX5_UART_1_PCLK, "uart_1_pclk", l4_sp_clk_parent, 1, 0, 0x7C, 21, 382 + 0, 0, 0, 0, 0, 0 }, 383 + { AGILEX5_SPTIMER_0_PCLK, "sptimer_0_pclk", l4_sp_clk_parent, 1, 0, 384 + 0x7C, 23, 0, 0, 0, 0, 0, 0 }, 385 + { AGILEX5_SPTIMER_1_PCLK, "sptimer_1_pclk", l4_sp_clk_parent, 1, 0, 386 + 0x7C, 24, 0, 0, 0, 0, 0, 0 }, 387 + 388 + /*NAND, SD/MMC and SoftPHY overall clocking*/ 389 + { AGILEX5_DFI_CLK, "dfi_clk", l4_mp_clk_parent, 1, 0, 0, 0, 0x44, 16, 390 + 2, 0, 0, 0 }, 391 + { AGILEX5_NAND_NF_CLK, "nand_nf_clk", dfi_clk_parent, 1, 0, 0x7C, 10, 392 + 0, 0, 0, 0, 0, 0 }, 393 + { AGILEX5_NAND_BCH_CLK, "nand_bch_clk", l4_mp_clk_parent, 1, 0, 0x7C, 394 + 10, 0, 0, 0, 0, 0, 0 }, 395 + { AGILEX5_SDMMC_SDPHY_REG_CLK, "sdmmc_sdphy_reg_clk", l4_mp_clk_parent, 396 + 1, 0, 0x7C, 5, 0, 0, 0, 0, 0, 0 }, 397 + { AGILEX5_SDMCLK, "sdmclk", dfi_clk_parent, 1, 0, 0x7C, 5, 0, 0, 0, 398 + 0, 0, 0 }, 399 + { AGILEX5_SOFTPHY_REG_PCLK, "softphy_reg_pclk", l4_mp_clk_parent, 1, 0, 400 + 0x7C, 26, 0, 0, 0, 0, 0, 0 }, 401 + { AGILEX5_SOFTPHY_PHY_CLK, "softphy_phy_clk", l4_mp_clk_parent, 1, 0, 402 + 0x7C, 26, 0x44, 16, 2, 0, 0, 0 }, 403 + { AGILEX5_SOFTPHY_CTRL_CLK, "softphy_ctrl_clk", dfi_clk_parent, 1, 0, 404 + 0x7C, 26, 0, 0, 0, 0, 0, 0 }, 405 + }; 406 + 407 + static int 408 + agilex5_clk_register_c_perip(const struct stratix10_perip_c_clock *clks, 409 + int nums, struct stratix10_clock_data *data) 410 + { 411 + struct clk_hw *hw_clk; 412 + void __iomem *base = data->base; 413 + int i; 414 + 415 + for (i = 0; i < nums; i++) { 416 + hw_clk = s10_register_periph(&clks[i], base); 417 + if (IS_ERR(hw_clk)) { 418 + pr_err("%s: failed to register clock %s\n", __func__, 419 + clks[i].name); 420 + continue; 421 + } 422 + data->clk_data.hws[clks[i].id] = hw_clk; 423 + } 424 + return 0; 425 + } 426 + 427 + static int 428 + agilex5_clk_register_cnt_perip(const struct agilex5_perip_cnt_clock *clks, 429 + int nums, struct stratix10_clock_data *data) 430 + { 431 + struct clk_hw *hw_clk; 432 + void __iomem *base = data->base; 433 + int i; 434 + 435 + for (i = 0; i < nums; i++) { 436 + hw_clk = agilex5_register_cnt_periph(&clks[i], base); 437 + if (IS_ERR(hw_clk)) { 438 + pr_err("%s: failed to register clock %s\n", __func__, 439 + clks[i].name); 440 + continue; 441 + } 442 + data->clk_data.hws[clks[i].id] = hw_clk; 443 + } 444 + 445 + return 0; 446 + } 447 + 448 + static int agilex5_clk_register_gate(const struct agilex5_gate_clock *clks, 449 + int nums, 450 + struct stratix10_clock_data *data) 451 + { 452 + struct clk_hw *hw_clk; 453 + void __iomem *base = data->base; 454 + int i; 455 + 456 + for (i = 0; i < nums; i++) { 457 + hw_clk = agilex5_register_gate(&clks[i], base); 458 + if (IS_ERR(hw_clk)) { 459 + pr_err("%s: failed to register clock %s\n", __func__, 460 + clks[i].name); 461 + continue; 462 + } 463 + data->clk_data.hws[clks[i].id] = hw_clk; 464 + } 465 + 466 + return 0; 467 + } 468 + 469 + static int agilex5_clk_register_pll(const struct agilex5_pll_clock *clks, 470 + int nums, struct stratix10_clock_data *data) 471 + { 472 + struct clk_hw *hw_clk; 473 + void __iomem *base = data->base; 474 + int i; 475 + 476 + for (i = 0; i < nums; i++) { 477 + hw_clk = agilex5_register_pll(&clks[i], base); 478 + if (IS_ERR(hw_clk)) { 479 + pr_err("%s: failed to register clock %s\n", __func__, 480 + clks[i].name); 481 + continue; 482 + } 483 + data->clk_data.hws[clks[i].id] = hw_clk; 484 + } 485 + 486 + return 0; 487 + } 488 + 489 + static int agilex5_clkmgr_init(struct platform_device *pdev) 490 + { 491 + struct device_node *np = pdev->dev.of_node; 492 + struct device *dev = &pdev->dev; 493 + struct stratix10_clock_data *clk_data; 494 + void __iomem *base; 495 + int i, num_clks; 496 + 497 + base = devm_platform_ioremap_resource(pdev, 0); 498 + if (IS_ERR(base)) 499 + return PTR_ERR(base); 500 + 501 + num_clks = AGILEX5_NUM_CLKS; 502 + 503 + clk_data = devm_kzalloc(dev, struct_size(clk_data, clk_data.hws, 504 + num_clks), GFP_KERNEL); 505 + if (!clk_data) 506 + return -ENOMEM; 507 + 508 + clk_data->base = base; 509 + clk_data->clk_data.num = num_clks; 510 + 511 + for (i = 0; i < num_clks; i++) 512 + clk_data->clk_data.hws[i] = ERR_PTR(-ENOENT); 513 + 514 + agilex5_clk_register_pll(agilex5_pll_clks, ARRAY_SIZE(agilex5_pll_clks), 515 + clk_data); 516 + 517 + /* mainPLL C0, C1, C2, C3 and periph PLL C0, C1, C2, C3*/ 518 + agilex5_clk_register_c_perip(agilex5_main_perip_c_clks, 519 + ARRAY_SIZE(agilex5_main_perip_c_clks), 520 + clk_data); 521 + 522 + agilex5_clk_register_cnt_perip(agilex5_main_perip_cnt_clks, 523 + ARRAY_SIZE(agilex5_main_perip_cnt_clks), 524 + clk_data); 525 + 526 + agilex5_clk_register_gate(agilex5_gate_clks, 527 + ARRAY_SIZE(agilex5_gate_clks), clk_data); 528 + 529 + of_clk_add_hw_provider(np, of_clk_hw_onecell_get, &clk_data->clk_data); 530 + return 0; 531 + } 532 + 533 + static int agilex5_clkmgr_probe(struct platform_device *pdev) 534 + { 535 + int (*probe_func)(struct platform_device *init_func); 536 + 537 + probe_func = of_device_get_match_data(&pdev->dev); 538 + if (!probe_func) 539 + return -ENODEV; 540 + return probe_func(pdev); 541 + } 542 + 543 + static const struct of_device_id agilex5_clkmgr_match_table[] = { 544 + { .compatible = "intel,agilex5-clkmgr", .data = agilex5_clkmgr_init }, 545 + {} 546 + }; 547 + 548 + static struct platform_driver agilex5_clkmgr_driver = { 549 + .probe = agilex5_clkmgr_probe, 550 + .driver = { 551 + .name = "agilex5-clkmgr", 552 + .suppress_bind_attrs = true, 553 + .of_match_table = agilex5_clkmgr_match_table, 554 + }, 555 + }; 556 + 557 + static int __init agilex5_clk_init(void) 558 + { 559 + return platform_driver_register(&agilex5_clkmgr_driver); 560 + } 561 + core_initcall(agilex5_clk_init);
+53
drivers/clk/socfpga/clk-gate-s10.c
··· 239 239 } 240 240 return hw_clk; 241 241 } 242 + 243 + struct clk_hw *agilex5_register_gate(const struct agilex5_gate_clock *clks, void __iomem *regbase) 244 + { 245 + struct clk_hw *hw_clk; 246 + struct socfpga_gate_clk *socfpga_clk; 247 + struct clk_init_data init; 248 + int ret; 249 + 250 + socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL); 251 + if (!socfpga_clk) 252 + return NULL; 253 + 254 + socfpga_clk->hw.reg = regbase + clks->gate_reg; 255 + socfpga_clk->hw.bit_idx = clks->gate_idx; 256 + 257 + gateclk_ops.enable = clk_gate_ops.enable; 258 + gateclk_ops.disable = clk_gate_ops.disable; 259 + 260 + socfpga_clk->fixed_div = clks->fixed_div; 261 + 262 + if (clks->div_reg) 263 + socfpga_clk->div_reg = regbase + clks->div_reg; 264 + else 265 + socfpga_clk->div_reg = NULL; 266 + 267 + socfpga_clk->width = clks->div_width; 268 + socfpga_clk->shift = clks->div_offset; 269 + 270 + if (clks->bypass_reg) 271 + socfpga_clk->bypass_reg = regbase + clks->bypass_reg; 272 + else 273 + socfpga_clk->bypass_reg = NULL; 274 + socfpga_clk->bypass_shift = clks->bypass_shift; 275 + 276 + if (streq(clks->name, "cs_pdbg_clk")) 277 + init.ops = &dbgclk_ops; 278 + else 279 + init.ops = &agilex_gateclk_ops; 280 + 281 + init.name = clks->name; 282 + init.flags = clks->flags; 283 + init.num_parents = clks->num_parents; 284 + init.parent_names = clks->parent_names; 285 + socfpga_clk->hw.hw.init = &init; 286 + hw_clk = &socfpga_clk->hw.hw; 287 + 288 + ret = clk_hw_register(NULL, &socfpga_clk->hw.hw); 289 + if (ret) { 290 + kfree(socfpga_clk); 291 + return ERR_PTR(ret); 292 + } 293 + return hw_clk; 294 + }
+41
drivers/clk/socfpga/clk-periph-s10.c
··· 214 214 } 215 215 return hw_clk; 216 216 } 217 + 218 + struct clk_hw *agilex5_register_cnt_periph(const struct agilex5_perip_cnt_clock *clks, 219 + void __iomem *regbase) 220 + { 221 + struct clk_hw *hw_clk; 222 + struct socfpga_periph_clk *periph_clk; 223 + struct clk_init_data init; 224 + const char *name = clks->name; 225 + int ret; 226 + 227 + periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL); 228 + if (WARN_ON(!periph_clk)) 229 + return NULL; 230 + 231 + if (clks->offset) 232 + periph_clk->hw.reg = regbase + clks->offset; 233 + else 234 + periph_clk->hw.reg = NULL; 235 + 236 + if (clks->bypass_reg) 237 + periph_clk->bypass_reg = regbase + clks->bypass_reg; 238 + else 239 + periph_clk->bypass_reg = NULL; 240 + periph_clk->bypass_shift = clks->bypass_shift; 241 + periph_clk->fixed_div = clks->fixed_divider; 242 + 243 + init.name = name; 244 + init.ops = &peri_cnt_clk_ops; 245 + init.flags = clks->flags; 246 + init.num_parents = clks->num_parents; 247 + init.parent_names = clks->parent_names; 248 + periph_clk->hw.hw.init = &init; 249 + hw_clk = &periph_clk->hw.hw; 250 + 251 + ret = clk_hw_register(NULL, hw_clk); 252 + if (ret) { 253 + kfree(periph_clk); 254 + return ERR_PTR(ret); 255 + } 256 + return hw_clk; 257 + }
+36
drivers/clk/socfpga/clk-pll-s10.c
··· 304 304 } 305 305 return hw_clk; 306 306 } 307 + 308 + struct clk_hw *agilex5_register_pll(const struct agilex5_pll_clock *clks, 309 + void __iomem *reg) 310 + { 311 + struct clk_hw *hw_clk; 312 + struct socfpga_pll *pll_clk; 313 + struct clk_init_data init; 314 + const char *name = clks->name; 315 + int ret; 316 + 317 + pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL); 318 + if (WARN_ON(!pll_clk)) 319 + return NULL; 320 + 321 + pll_clk->hw.reg = reg + clks->offset; 322 + 323 + if (streq(name, SOCFPGA_BOOT_CLK)) 324 + init.ops = &clk_boot_ops; 325 + else 326 + init.ops = &agilex_clk_pll_ops; 327 + 328 + init.name = name; 329 + init.flags = clks->flags; 330 + init.num_parents = clks->num_parents; 331 + init.parent_names = clks->parent_names; 332 + pll_clk->hw.hw.init = &init; 333 + pll_clk->hw.bit_idx = SOCFPGA_PLL_POWER; 334 + hw_clk = &pll_clk->hw.hw; 335 + 336 + ret = clk_hw_register(NULL, hw_clk); 337 + if (ret) { 338 + kfree(pll_clk); 339 + return ERR_PTR(ret); 340 + } 341 + return hw_clk; 342 + }
+43
drivers/clk/socfpga/stratix10-clk.h
··· 73 73 u8 fixed_div; 74 74 }; 75 75 76 + struct agilex5_pll_clock { 77 + unsigned int id; 78 + const char *name; 79 + const char * const *parent_names; 80 + u8 num_parents; 81 + unsigned long flags; 82 + unsigned long offset; 83 + }; 84 + 85 + struct agilex5_perip_cnt_clock { 86 + unsigned int id; 87 + const char *name; 88 + const char * const *parent_names; 89 + u8 num_parents; 90 + unsigned long flags; 91 + unsigned long offset; 92 + u8 fixed_divider; 93 + unsigned long bypass_reg; 94 + unsigned long bypass_shift; 95 + }; 96 + 97 + struct agilex5_gate_clock { 98 + unsigned int id; 99 + const char *name; 100 + const char * const *parent_names; 101 + u8 num_parents; 102 + unsigned long flags; 103 + unsigned long gate_reg; 104 + u8 gate_idx; 105 + unsigned long div_reg; 106 + u8 div_offset; 107 + u8 div_width; 108 + unsigned long bypass_reg; 109 + u8 bypass_shift; 110 + u8 fixed_div; 111 + }; 112 + 76 113 struct clk_hw *s10_register_pll(const struct stratix10_pll_clock *clks, 77 114 void __iomem *reg); 78 115 struct clk_hw *agilex_register_pll(const struct stratix10_pll_clock *clks, 79 116 void __iomem *reg); 80 117 struct clk_hw *n5x_register_pll(const struct stratix10_pll_clock *clks, 81 118 void __iomem *reg); 119 + struct clk_hw *agilex5_register_pll(const struct agilex5_pll_clock *clks, 120 + void __iomem *reg); 121 + struct clk_hw *agilex5_register_cnt_periph(const struct agilex5_perip_cnt_clock *clks, 122 + void __iomem *regbase); 123 + struct clk_hw *agilex5_register_gate(const struct agilex5_gate_clock *clks, 124 + void __iomem *regbase); 82 125 struct clk_hw *s10_register_periph(const struct stratix10_perip_c_clock *clks, 83 126 void __iomem *reg); 84 127 struct clk_hw *n5x_register_periph(const struct n5x_perip_c_clock *clks,