1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2019, Intel Corporation 4 */ 5 #include <linux/slab.h> 6 #include <linux/clk-provider.h> 7 #include <linux/of.h> 8 #include <linux/platform_device.h> 9 10 #include <dt-bindings/clock/agilex-clock.h> 11 12 #include "stratix10-clk.h" 13 14 static const struct clk_parent_data pll_mux[] = { 15 { .fw_name = "osc1", 16 .name = "osc1", }, 17 { .fw_name = "cb-intosc-hs-div2-clk", 18 .name = "cb-intosc-hs-div2-clk", }, 19 { .fw_name = "f2s-free-clk", 20 .name = "f2s-free-clk", }, 21 }; 22 23 static const struct clk_parent_data boot_mux[] = { 24 { .fw_name = "osc1", 25 .name = "osc1", }, 26 { .fw_name = "cb-intosc-hs-div2-clk", 27 .name = "cb-intosc-hs-div2-clk", }, 28 }; 29 30 static const struct clk_parent_data mpu_free_mux[] = { 31 { .fw_name = "main_pll_c0", 32 .name = "main_pll_c0", }, 33 { .fw_name = "peri_pll_c0", 34 .name = "peri_pll_c0", }, 35 { .fw_name = "osc1", 36 .name = "osc1", }, 37 { .fw_name = "cb-intosc-hs-div2-clk", 38 .name = "cb-intosc-hs-div2-clk", }, 39 { .fw_name = "f2s-free-clk", 40 .name = "f2s-free-clk", }, 41 }; 42 43 static const struct clk_parent_data noc_free_mux[] = { 44 { .fw_name = "main_pll_c1", 45 .name = "main_pll_c1", }, 46 { .fw_name = "peri_pll_c1", 47 .name = "peri_pll_c1", }, 48 { .fw_name = "osc1", 49 .name = "osc1", }, 50 { .fw_name = "cb-intosc-hs-div2-clk", 51 .name = "cb-intosc-hs-div2-clk", }, 52 { .fw_name = "f2s-free-clk", 53 .name = "f2s-free-clk", }, 54 }; 55 56 static const struct clk_parent_data emaca_free_mux[] = { 57 { .fw_name = "main_pll_c2", 58 .name = "main_pll_c2", }, 59 { .fw_name = "peri_pll_c2", 60 .name = "peri_pll_c2", }, 61 { .fw_name = "osc1", 62 .name = "osc1", }, 63 { .fw_name = "cb-intosc-hs-div2-clk", 64 .name = "cb-intosc-hs-div2-clk", }, 65 { .fw_name = "f2s-free-clk", 66 .name = "f2s-free-clk", }, 67 }; 68 69 static const struct clk_parent_data emacb_free_mux[] = { 70 { .fw_name = "main_pll_c3", 71 .name = "main_pll_c3", }, 72 { .fw_name = "peri_pll_c3", 73 .name = "peri_pll_c3", }, 74 { .fw_name = "osc1", 75 .name = "osc1", }, 76 { .fw_name = "cb-intosc-hs-div2-clk", 77 .name = "cb-intosc-hs-div2-clk", }, 78 { .fw_name = "f2s-free-clk", 79 .name = "f2s-free-clk", }, 80 }; 81 82 static const struct clk_parent_data emac_ptp_free_mux[] = { 83 { .fw_name = "main_pll_c3", 84 .name = "main_pll_c3", }, 85 { .fw_name = "peri_pll_c3", 86 .name = "peri_pll_c3", }, 87 { .fw_name = "osc1", 88 .name = "osc1", }, 89 { .fw_name = "cb-intosc-hs-div2-clk", 90 .name = "cb-intosc-hs-div2-clk", }, 91 { .fw_name = "f2s-free-clk", 92 .name = "f2s-free-clk", }, 93 }; 94 95 static const struct clk_parent_data gpio_db_free_mux[] = { 96 { .fw_name = "main_pll_c3", 97 .name = "main_pll_c3", }, 98 { .fw_name = "peri_pll_c3", 99 .name = "peri_pll_c3", }, 100 { .fw_name = "osc1", 101 .name = "osc1", }, 102 { .fw_name = "cb-intosc-hs-div2-clk", 103 .name = "cb-intosc-hs-div2-clk", }, 104 { .fw_name = "f2s-free-clk", 105 .name = "f2s-free-clk", }, 106 }; 107 108 static const struct clk_parent_data psi_ref_free_mux[] = { 109 { .fw_name = "main_pll_c2", 110 .name = "main_pll_c2", }, 111 { .fw_name = "peri_pll_c2", 112 .name = "peri_pll_c2", }, 113 { .fw_name = "osc1", 114 .name = "osc1", }, 115 { .fw_name = "cb-intosc-hs-div2-clk", 116 .name = "cb-intosc-hs-div2-clk", }, 117 { .fw_name = "f2s-free-clk", 118 .name = "f2s-free-clk", }, 119 }; 120 121 static const struct clk_parent_data sdmmc_free_mux[] = { 122 { .fw_name = "main_pll_c3", 123 .name = "main_pll_c3", }, 124 { .fw_name = "peri_pll_c3", 125 .name = "peri_pll_c3", }, 126 { .fw_name = "osc1", 127 .name = "osc1", }, 128 { .fw_name = "cb-intosc-hs-div2-clk", 129 .name = "cb-intosc-hs-div2-clk", }, 130 { .fw_name = "f2s-free-clk", 131 .name = "f2s-free-clk", }, 132 }; 133 134 static const struct clk_parent_data s2f_usr0_free_mux[] = { 135 { .fw_name = "main_pll_c2", 136 .name = "main_pll_c2", }, 137 { .fw_name = "peri_pll_c2", 138 .name = "peri_pll_c2", }, 139 { .fw_name = "osc1", 140 .name = "osc1", }, 141 { .fw_name = "cb-intosc-hs-div2-clk", 142 .name = "cb-intosc-hs-div2-clk", }, 143 { .fw_name = "f2s-free-clk", 144 .name = "f2s-free-clk", }, 145 }; 146 147 static const struct clk_parent_data s2f_usr1_free_mux[] = { 148 { .fw_name = "main_pll_c2", 149 .name = "main_pll_c2", }, 150 { .fw_name = "peri_pll_c2", 151 .name = "peri_pll_c2", }, 152 { .fw_name = "osc1", 153 .name = "osc1", }, 154 { .fw_name = "cb-intosc-hs-div2-clk", 155 .name = "cb-intosc-hs-div2-clk", }, 156 { .fw_name = "f2s-free-clk", 157 .name = "f2s-free-clk", }, 158 }; 159 160 static const struct clk_parent_data mpu_mux[] = { 161 { .fw_name = "mpu_free_clk", 162 .name = "mpu_free_clk", }, 163 { .fw_name = "boot_clk", 164 .name = "boot_clk", }, 165 }; 166 167 static const struct clk_parent_data emac_mux[] = { 168 { .fw_name = "emaca_free_clk", 169 .name = "emaca_free_clk", }, 170 { .fw_name = "emacb_free_clk", 171 .name = "emacb_free_clk", }, 172 { .fw_name = "boot_clk", 173 .name = "boot_clk", }, 174 }; 175 176 static const struct clk_parent_data noc_mux[] = { 177 { .fw_name = "noc_free_clk", 178 .name = "noc_free_clk", }, 179 { .fw_name = "boot_clk", 180 .name = "boot_clk", }, 181 }; 182 183 static const struct clk_parent_data sdmmc_mux[] = { 184 { .fw_name = "sdmmc_free_clk", 185 .name = "sdmmc_free_clk", }, 186 { .fw_name = "boot_clk", 187 .name = "boot_clk", }, 188 }; 189 190 static const struct clk_parent_data s2f_user0_mux[] = { 191 { .fw_name = "s2f_user0_free_clk", 192 .name = "s2f_user0_free_clk", }, 193 { .fw_name = "boot_clk", 194 .name = "boot_clk", }, 195 }; 196 197 static const struct clk_parent_data s2f_user1_mux[] = { 198 { .fw_name = "s2f_user1_free_clk", 199 .name = "s2f_user1_free_clk", }, 200 { .fw_name = "boot_clk", 201 .name = "boot_clk", }, 202 }; 203 204 static const struct clk_parent_data psi_mux[] = { 205 { .fw_name = "psi_ref_free_clk", 206 .name = "psi_ref_free_clk", }, 207 { .fw_name = "boot_clk", 208 .name = "boot_clk", }, 209 }; 210 211 static const struct clk_parent_data gpio_db_mux[] = { 212 { .fw_name = "gpio_db_free_clk", 213 .name = "gpio_db_free_clk", }, 214 { .fw_name = "boot_clk", 215 .name = "boot_clk", }, 216 }; 217 218 static const struct clk_parent_data emac_ptp_mux[] = { 219 { .fw_name = "emac_ptp_free_clk", 220 .name = "emac_ptp_free_clk", }, 221 { .fw_name = "boot_clk", 222 .name = "boot_clk", }, 223 }; 224 225 /* clocks in AO (always on) controller */ 226 static const struct stratix10_pll_clock agilex_pll_clks[] = { 227 { AGILEX_BOOT_CLK, "boot_clk", boot_mux, ARRAY_SIZE(boot_mux), 0, 228 0x0}, 229 { AGILEX_MAIN_PLL_CLK, "main_pll", pll_mux, ARRAY_SIZE(pll_mux), 230 0, 0x48}, 231 { AGILEX_PERIPH_PLL_CLK, "periph_pll", pll_mux, ARRAY_SIZE(pll_mux), 232 0, 0x9c}, 233 }; 234 235 static const struct n5x_perip_c_clock n5x_main_perip_c_clks[] = { 236 { AGILEX_MAIN_PLL_C0_CLK, "main_pll_c0", "main_pll", NULL, 1, 0, 0x54, 0}, 237 { AGILEX_MAIN_PLL_C1_CLK, "main_pll_c1", "main_pll", NULL, 1, 0, 0x54, 8}, 238 { AGILEX_MAIN_PLL_C2_CLK, "main_pll_c2", "main_pll", NULL, 1, 0, 0x54, 16}, 239 { AGILEX_MAIN_PLL_C3_CLK, "main_pll_c3", "main_pll", NULL, 1, 0, 0x54, 24}, 240 { AGILEX_PERIPH_PLL_C0_CLK, "peri_pll_c0", "periph_pll", NULL, 1, 0, 0xA8, 0}, 241 { AGILEX_PERIPH_PLL_C1_CLK, "peri_pll_c1", "periph_pll", NULL, 1, 0, 0xA8, 8}, 242 { AGILEX_PERIPH_PLL_C2_CLK, "peri_pll_c2", "periph_pll", NULL, 1, 0, 0xA8, 16}, 243 { AGILEX_PERIPH_PLL_C3_CLK, "peri_pll_c3", "periph_pll", NULL, 1, 0, 0xA8, 24}, 244 }; 245 246 static const struct stratix10_perip_c_clock agilex_main_perip_c_clks[] = { 247 { AGILEX_MAIN_PLL_C0_CLK, "main_pll_c0", "main_pll", NULL, 1, 0, 0x58}, 248 { AGILEX_MAIN_PLL_C1_CLK, "main_pll_c1", "main_pll", NULL, 1, 0, 0x5C}, 249 { AGILEX_MAIN_PLL_C2_CLK, "main_pll_c2", "main_pll", NULL, 1, 0, 0x64}, 250 { AGILEX_MAIN_PLL_C3_CLK, "main_pll_c3", "main_pll", NULL, 1, 0, 0x68}, 251 { AGILEX_PERIPH_PLL_C0_CLK, "peri_pll_c0", "periph_pll", NULL, 1, 0, 0xAC}, 252 { AGILEX_PERIPH_PLL_C1_CLK, "peri_pll_c1", "periph_pll", NULL, 1, 0, 0xB0}, 253 { AGILEX_PERIPH_PLL_C2_CLK, "peri_pll_c2", "periph_pll", NULL, 1, 0, 0xB8}, 254 { AGILEX_PERIPH_PLL_C3_CLK, "peri_pll_c3", "periph_pll", NULL, 1, 0, 0xBC}, 255 }; 256 257 static const struct stratix10_perip_cnt_clock agilex_main_perip_cnt_clks[] = { 258 { AGILEX_MPU_FREE_CLK, "mpu_free_clk", NULL, mpu_free_mux, ARRAY_SIZE(mpu_free_mux), 259 0, 0x3C, 0, 0, 0}, 260 { AGILEX_NOC_FREE_CLK, "noc_free_clk", NULL, noc_free_mux, ARRAY_SIZE(noc_free_mux), 261 0, 0x40, 0, 0, 0}, 262 { AGILEX_L4_SYS_FREE_CLK, "l4_sys_free_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 263 0, 4, 0x30, 1}, 264 { AGILEX_EMAC_A_FREE_CLK, "emaca_free_clk", NULL, emaca_free_mux, ARRAY_SIZE(emaca_free_mux), 265 0, 0xD4, 0, 0x88, 0}, 266 { AGILEX_EMAC_B_FREE_CLK, "emacb_free_clk", NULL, emacb_free_mux, ARRAY_SIZE(emacb_free_mux), 267 0, 0xD8, 0, 0x88, 1}, 268 { AGILEX_EMAC_PTP_FREE_CLK, "emac_ptp_free_clk", NULL, emac_ptp_free_mux, 269 ARRAY_SIZE(emac_ptp_free_mux), 0, 0xDC, 0, 0x88, 2}, 270 { AGILEX_GPIO_DB_FREE_CLK, "gpio_db_free_clk", NULL, gpio_db_free_mux, 271 ARRAY_SIZE(gpio_db_free_mux), 0, 0xE0, 0, 0x88, 3}, 272 { AGILEX_SDMMC_FREE_CLK, "sdmmc_free_clk", NULL, sdmmc_free_mux, 273 ARRAY_SIZE(sdmmc_free_mux), 0, 0xE4, 0, 0, 0}, 274 { AGILEX_S2F_USER0_FREE_CLK, "s2f_user0_free_clk", NULL, s2f_usr0_free_mux, 275 ARRAY_SIZE(s2f_usr0_free_mux), 0, 0xE8, 0, 0x30, 2}, 276 { AGILEX_S2F_USER1_FREE_CLK, "s2f_user1_free_clk", NULL, s2f_usr1_free_mux, 277 ARRAY_SIZE(s2f_usr1_free_mux), 0, 0xEC, 0, 0x88, 5}, 278 { AGILEX_PSI_REF_FREE_CLK, "psi_ref_free_clk", NULL, psi_ref_free_mux, 279 ARRAY_SIZE(psi_ref_free_mux), 0, 0xF0, 0, 0x88, 6}, 280 }; 281 282 static const struct stratix10_gate_clock agilex_gate_clks[] = { 283 { AGILEX_MPU_CLK, "mpu_clk", NULL, mpu_mux, ARRAY_SIZE(mpu_mux), 0, 0x24, 284 0, 0, 0, 0, 0x30, 0, 0}, 285 { AGILEX_MPU_PERIPH_CLK, "mpu_periph_clk", "mpu_clk", NULL, 1, 0, 0x24, 286 0, 0, 0, 0, 0, 0, 4}, 287 { AGILEX_MPU_CCU_CLK, "mpu_ccu_clk", "mpu_clk", NULL, 1, 0, 0x24, 288 0, 0, 0, 0, 0, 0, 2}, 289 { AGILEX_L4_MAIN_CLK, "l4_main_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24, 290 1, 0x44, 0, 2, 0x30, 1, 0}, 291 { AGILEX_L4_MP_CLK, "l4_mp_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24, 292 2, 0x44, 8, 2, 0x30, 1, 0}, 293 /* 294 * The l4_sp_clk feeds a 100 MHz clock to various peripherals, one of them 295 * being the SP timers, thus cannot get gated. 296 */ 297 { AGILEX_L4_SP_CLK, "l4_sp_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), CLK_IS_CRITICAL, 0x24, 298 3, 0x44, 16, 2, 0x30, 1, 0}, 299 { AGILEX_CS_AT_CLK, "cs_at_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24, 300 4, 0x44, 24, 2, 0x30, 1, 0}, 301 { AGILEX_CS_TRACE_CLK, "cs_trace_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24, 302 4, 0x44, 26, 2, 0x30, 1, 0}, 303 { AGILEX_CS_PDBG_CLK, "cs_pdbg_clk", "cs_at_clk", NULL, 1, 0, 0x24, 304 4, 0x44, 28, 1, 0, 0, 0}, 305 { AGILEX_CS_TIMER_CLK, "cs_timer_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24, 306 5, 0, 0, 0, 0x30, 1, 0}, 307 { AGILEX_EMAC0_CLK, "emac0_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0x7C, 308 0, 0, 0, 0, 0x94, 26, 0}, 309 { AGILEX_EMAC1_CLK, "emac1_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0x7C, 310 1, 0, 0, 0, 0x94, 27, 0}, 311 { AGILEX_EMAC2_CLK, "emac2_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0x7C, 312 2, 0, 0, 0, 0x94, 28, 0}, 313 { AGILEX_EMAC_PTP_CLK, "emac_ptp_clk", NULL, emac_ptp_mux, ARRAY_SIZE(emac_ptp_mux), 0, 0x7C, 314 3, 0, 0, 0, 0x88, 2, 0}, 315 { AGILEX_GPIO_DB_CLK, "gpio_db_clk", NULL, gpio_db_mux, ARRAY_SIZE(gpio_db_mux), 0, 0x7C, 316 4, 0x98, 0, 16, 0x88, 3, 0}, 317 { AGILEX_SDMMC_CLK, "sdmmc_clk", NULL, sdmmc_mux, ARRAY_SIZE(sdmmc_mux), 0, 0x7C, 318 5, 0, 0, 0, 0x88, 4, 4}, 319 { AGILEX_S2F_USER0_CLK, "s2f_user0_clk", NULL, s2f_user0_mux, ARRAY_SIZE(s2f_user0_mux), 0, 0x24, 320 6, 0, 0, 0, 0x30, 2, 0}, 321 { AGILEX_S2F_USER1_CLK, "s2f_user1_clk", NULL, s2f_user1_mux, ARRAY_SIZE(s2f_user1_mux), 0, 0x7C, 322 6, 0, 0, 0, 0x88, 5, 0}, 323 { AGILEX_PSI_REF_CLK, "psi_ref_clk", NULL, psi_mux, ARRAY_SIZE(psi_mux), 0, 0x7C, 324 7, 0, 0, 0, 0x88, 6, 0}, 325 { AGILEX_USB_CLK, "usb_clk", "l4_mp_clk", NULL, 1, 0, 0x7C, 326 8, 0, 0, 0, 0, 0, 0}, 327 { AGILEX_SPI_M_CLK, "spi_m_clk", "l4_mp_clk", NULL, 1, 0, 0x7C, 328 9, 0, 0, 0, 0, 0, 0}, 329 { AGILEX_NAND_X_CLK, "nand_x_clk", "l4_mp_clk", NULL, 1, 0, 0x7C, 330 10, 0, 0, 0, 0, 0, 0}, 331 { AGILEX_NAND_CLK, "nand_clk", "nand_x_clk", NULL, 1, 0, 0x7C, 332 10, 0, 0, 0, 0, 0, 4}, 333 { AGILEX_NAND_ECC_CLK, "nand_ecc_clk", "nand_x_clk", NULL, 1, 0, 0x7C, 334 10, 0, 0, 0, 0, 0, 4}, 335 }; 336 337 static int n5x_clk_register_c_perip(const struct n5x_perip_c_clock *clks, 338 int nums, struct stratix10_clock_data *data) 339 { 340 struct clk_hw *hw_clk; 341 void __iomem *base = data->base; 342 int i; 343 344 for (i = 0; i < nums; i++) { 345 hw_clk = n5x_register_periph(&clks[i], base); 346 if (IS_ERR(hw_clk)) { 347 pr_err("%s: failed to register clock %s\n", 348 __func__, clks[i].name); 349 continue; 350 } 351 data->clk_data.hws[clks[i].id] = hw_clk; 352 } 353 return 0; 354 } 355 356 static int agilex_clk_register_c_perip(const struct stratix10_perip_c_clock *clks, 357 int nums, struct stratix10_clock_data *data) 358 { 359 struct clk_hw *hw_clk; 360 void __iomem *base = data->base; 361 int i; 362 363 for (i = 0; i < nums; i++) { 364 hw_clk = s10_register_periph(&clks[i], base); 365 if (IS_ERR(hw_clk)) { 366 pr_err("%s: failed to register clock %s\n", 367 __func__, clks[i].name); 368 continue; 369 } 370 data->clk_data.hws[clks[i].id] = hw_clk; 371 } 372 return 0; 373 } 374 375 static int agilex_clk_register_cnt_perip(const struct stratix10_perip_cnt_clock *clks, 376 int nums, struct stratix10_clock_data *data) 377 { 378 struct clk_hw *hw_clk; 379 void __iomem *base = data->base; 380 int i; 381 382 for (i = 0; i < nums; i++) { 383 hw_clk = s10_register_cnt_periph(&clks[i], base); 384 if (IS_ERR(hw_clk)) { 385 pr_err("%s: failed to register clock %s\n", 386 __func__, clks[i].name); 387 continue; 388 } 389 data->clk_data.hws[clks[i].id] = hw_clk; 390 } 391 392 return 0; 393 } 394 395 static int agilex_clk_register_gate(const struct stratix10_gate_clock *clks, 396 int nums, struct stratix10_clock_data *data) 397 { 398 struct clk_hw *hw_clk; 399 void __iomem *base = data->base; 400 int i; 401 402 for (i = 0; i < nums; i++) { 403 hw_clk = agilex_register_gate(&clks[i], base); 404 if (IS_ERR(hw_clk)) { 405 pr_err("%s: failed to register clock %s\n", 406 __func__, clks[i].name); 407 continue; 408 } 409 data->clk_data.hws[clks[i].id] = hw_clk; 410 } 411 412 return 0; 413 } 414 415 static int agilex_clk_register_pll(const struct stratix10_pll_clock *clks, 416 int nums, struct stratix10_clock_data *data) 417 { 418 struct clk_hw *hw_clk; 419 void __iomem *base = data->base; 420 int i; 421 422 for (i = 0; i < nums; i++) { 423 hw_clk = agilex_register_pll(&clks[i], base); 424 if (IS_ERR(hw_clk)) { 425 pr_err("%s: failed to register clock %s\n", 426 __func__, clks[i].name); 427 continue; 428 } 429 data->clk_data.hws[clks[i].id] = hw_clk; 430 } 431 432 return 0; 433 } 434 435 static int n5x_clk_register_pll(const struct stratix10_pll_clock *clks, 436 int nums, struct stratix10_clock_data *data) 437 { 438 struct clk_hw *hw_clk; 439 void __iomem *base = data->base; 440 int i; 441 442 for (i = 0; i < nums; i++) { 443 hw_clk = n5x_register_pll(&clks[i], base); 444 if (IS_ERR(hw_clk)) { 445 pr_err("%s: failed to register clock %s\n", 446 __func__, clks[i].name); 447 continue; 448 } 449 data->clk_data.hws[clks[i].id] = hw_clk; 450 } 451 452 return 0; 453 } 454 455 static int agilex_clkmgr_init(struct platform_device *pdev) 456 { 457 struct device_node *np = pdev->dev.of_node; 458 struct device *dev = &pdev->dev; 459 struct stratix10_clock_data *clk_data; 460 void __iomem *base; 461 int i, num_clks; 462 463 base = devm_platform_ioremap_resource(pdev, 0); 464 if (IS_ERR(base)) 465 return PTR_ERR(base); 466 467 num_clks = AGILEX_NUM_CLKS; 468 469 clk_data = devm_kzalloc(dev, struct_size(clk_data, clk_data.hws, 470 num_clks), GFP_KERNEL); 471 if (!clk_data) 472 return -ENOMEM; 473 474 clk_data->clk_data.num = num_clks; 475 clk_data->base = base; 476 477 for (i = 0; i < num_clks; i++) 478 clk_data->clk_data.hws[i] = ERR_PTR(-ENOENT); 479 480 agilex_clk_register_pll(agilex_pll_clks, ARRAY_SIZE(agilex_pll_clks), clk_data); 481 482 agilex_clk_register_c_perip(agilex_main_perip_c_clks, 483 ARRAY_SIZE(agilex_main_perip_c_clks), clk_data); 484 485 agilex_clk_register_cnt_perip(agilex_main_perip_cnt_clks, 486 ARRAY_SIZE(agilex_main_perip_cnt_clks), 487 clk_data); 488 489 agilex_clk_register_gate(agilex_gate_clks, ARRAY_SIZE(agilex_gate_clks), 490 clk_data); 491 of_clk_add_hw_provider(np, of_clk_hw_onecell_get, &clk_data->clk_data); 492 return 0; 493 } 494 495 static int n5x_clkmgr_init(struct platform_device *pdev) 496 { 497 struct device_node *np = pdev->dev.of_node; 498 struct device *dev = &pdev->dev; 499 struct stratix10_clock_data *clk_data; 500 void __iomem *base; 501 int i, num_clks; 502 503 base = devm_platform_ioremap_resource(pdev, 0); 504 if (IS_ERR(base)) 505 return PTR_ERR(base); 506 507 num_clks = AGILEX_NUM_CLKS; 508 509 clk_data = devm_kzalloc(dev, struct_size(clk_data, clk_data.hws, 510 num_clks), GFP_KERNEL); 511 if (!clk_data) 512 return -ENOMEM; 513 514 clk_data->base = base; 515 clk_data->clk_data.num = num_clks; 516 517 for (i = 0; i < num_clks; i++) 518 clk_data->clk_data.hws[i] = ERR_PTR(-ENOENT); 519 520 n5x_clk_register_pll(agilex_pll_clks, ARRAY_SIZE(agilex_pll_clks), clk_data); 521 522 n5x_clk_register_c_perip(n5x_main_perip_c_clks, 523 ARRAY_SIZE(n5x_main_perip_c_clks), clk_data); 524 525 agilex_clk_register_cnt_perip(agilex_main_perip_cnt_clks, 526 ARRAY_SIZE(agilex_main_perip_cnt_clks), 527 clk_data); 528 529 agilex_clk_register_gate(agilex_gate_clks, ARRAY_SIZE(agilex_gate_clks), 530 clk_data); 531 of_clk_add_hw_provider(np, of_clk_hw_onecell_get, &clk_data->clk_data); 532 return 0; 533 } 534 535 static int agilex_clkmgr_probe(struct platform_device *pdev) 536 { 537 int (*probe_func)(struct platform_device *init_func); 538 539 probe_func = of_device_get_match_data(&pdev->dev); 540 if (!probe_func) 541 return -ENODEV; 542 return probe_func(pdev); 543 } 544 545 static const struct of_device_id agilex_clkmgr_match_table[] = { 546 { .compatible = "intel,agilex-clkmgr", 547 .data = agilex_clkmgr_init }, 548 { .compatible = "intel,easic-n5x-clkmgr", 549 .data = n5x_clkmgr_init }, 550 { } 551 }; 552 553 static struct platform_driver agilex_clkmgr_driver = { 554 .probe = agilex_clkmgr_probe, 555 .driver = { 556 .name = "agilex-clkmgr", 557 .suppress_bind_attrs = true, 558 .of_match_table = agilex_clkmgr_match_table, 559 }, 560 }; 561 562 static int __init agilex_clk_init(void) 563 { 564 return platform_driver_register(&agilex_clkmgr_driver); 565 } 566 core_initcall(agilex_clk_init); 567