FILE
clk-agilex5.c
File preview with syntax highlighting.
linux-6.19.14/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 */ 15static const char * const boot_pll_parents[] = { 16 "osc1", 17 "cb-intosc-hs-div2-clk", 18}; 19 20static const char * const main_pll_parents[] = { 21 "osc1", 22 "cb-intosc-hs-div2-clk", 23 "f2s-free-clk", 24}; 25 26static const char * const periph_pll_parents[] = { 27 "osc1", 28 "cb-intosc-hs-div2-clk", 29}; 30 31/* Core free muxes */ 32static 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 40static 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 48static const char * const core2_free_mux[] = { 49 "main_pll_c0", 50 "osc1", 51 "cb-intosc-hs-div2-clk", 52 "f2s-free-clk", 53}; 54 55static const char * const core3_free_mux[] = { 56 "main_pll_c0", 57 "osc1", 58 "cb-intosc-hs-div2-clk", 59 "f2s-free-clk", 60}; 61 62static 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 70static 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 78static 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 86static 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 94static 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 102static 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 110static 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 118static 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 126static 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 134static 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 */ 143static const char * const core0_mux[] = { 144 "core0_free_clk", 145 "boot_clk", 146}; 147 148static const char * const core1_mux[] = { 149 "core1_free_clk", 150 "boot_clk", 151}; 152 153static const char * const core2_mux[] = { 154 "core2_free_clk", 155 "boot_clk", 156}; 157 158static const char * const core3_mux[] = { 159 "core3_free_clk", 160 "boot_clk", 161}; 162 163static const char * const dsu_mux[] = { 164 "dsu_free_clk", 165 "boot_clk", 166}; 167 168static const char * const noc_mux[] = { 169 "noc_free_clk", 170 "boot_clk", 171}; 172 173static const char * const emac_mux[] = { 174 "emaca_free_clk", 175 "emacb_free_clk", 176 "boot_clk", 177}; 178 179static const char * const s2f_user0_mux[] = { 180 "s2f_user0_free_clk", 181 "boot_clk", 182}; 183 184static const char * const s2f_user1_mux[] = { 185 "s2f_user1_free_clk", 186 "boot_clk", 187}; 188 189static const char * const psi_mux[] = { 190 "psi_ref_free_clk", 191 "boot_clk", 192}; 193 194static const char * const gpio_db_mux[] = { 195 "gpio_db_free_clk", 196 "boot_clk", 197}; 198 199static const char * const emac_ptp_mux[] = { 200 "emac_ptp_free_clk", 201 "boot_clk", 202}; 203 204static const char * const usb31_mux[] = { 205 "usb31_free_clk", 206 "boot_clk", 207}; 208 209static 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. */ 237static 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 */ 257static 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 288static const char * const cs_pdbg_parents[] = { "cs_at_clk" }; 289static const char * const usb31_bus_clk_early_parents[] = { "l4_main_clk" }; 290static const char * const l4_mp_clk_parent[] = { "l4_mp_clk" }; 291static const char * const l4_sp_clk_parent[] = { "l4_sp_clk" }; 292static const char * const dfi_clk_parent[] = { "dfi_clk" }; 293 294/* SW Clock gate enabled clocks */ 295static 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 407static int 408agilex5_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 427static int 428agilex5_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 448static 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 469static 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 489static 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 533static 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 543static const struct of_device_id agilex5_clkmgr_match_table[] = { 544 { .compatible = "intel,agilex5-clkmgr", .data = agilex5_clkmgr_init }, 545 {} 546}; 547 548static 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 557static int __init agilex5_clk_init(void) 558{ 559 return platform_driver_register(&agilex5_clkmgr_driver); 560} 561core_initcall(agilex5_clk_init);
~/
Read-only file preview.