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