root/drivers/clk/socfpga/clk-s10.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. s10_clk_register_c_perip
  2. s10_clk_register_cnt_perip
  3. s10_clk_register_gate
  4. s10_clk_register_pll
  5. __socfpga_s10_clk_init
  6. s10_clkmgr_init
  7. s10_clkmgr_probe
  8. s10_clk_init

   1 // SPDX-License-Identifier:     GPL-2.0
   2 /*
   3  * Copyright (C) 2017, 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/stratix10-clock.h>
  12 
  13 #include "stratix10-clk.h"
  14 
  15 static const char * const pll_mux[] = { "osc1", "cb-intosc-hs-div2-clk",
  16                                         "f2s-free-clk",};
  17 static const char * const cntr_mux[] = { "main_pll", "periph_pll",
  18                                          "osc1", "cb-intosc-hs-div2-clk",
  19                                          "f2s-free-clk"};
  20 static const char * const boot_mux[] = { "osc1", "cb-intosc-hs-div2-clk",};
  21 
  22 static const char * const noc_free_mux[] = {"main_noc_base_clk",
  23                                             "peri_noc_base_clk",
  24                                             "osc1", "cb-intosc-hs-div2-clk",
  25                                             "f2s-free-clk"};
  26 
  27 static const char * const emaca_free_mux[] = {"peri_emaca_clk", "boot_clk"};
  28 static const char * const emacb_free_mux[] = {"peri_emacb_clk", "boot_clk"};
  29 static const char * const emac_ptp_free_mux[] = {"peri_emac_ptp_clk", "boot_clk"};
  30 static const char * const gpio_db_free_mux[] = {"peri_gpio_db_clk", "boot_clk"};
  31 static const char * const sdmmc_free_mux[] = {"main_sdmmc_clk", "boot_clk"};
  32 static const char * const s2f_usr1_free_mux[] = {"peri_s2f_usr1_clk", "boot_clk"};
  33 static const char * const psi_ref_free_mux[] = {"peri_psi_ref_clk", "boot_clk"};
  34 static const char * const mpu_mux[] = { "mpu_free_clk", "boot_clk",};
  35 
  36 static const char * const s2f_usr0_mux[] = {"f2s-free-clk", "boot_clk"};
  37 static const char * const emac_mux[] = {"emaca_free_clk", "emacb_free_clk"};
  38 static const char * const noc_mux[] = {"noc_free_clk", "boot_clk"};
  39 
  40 static const char * const mpu_free_mux[] = {"main_mpu_base_clk",
  41                                             "peri_mpu_base_clk",
  42                                             "osc1", "cb-intosc-hs-div2-clk",
  43                                             "f2s-free-clk"};
  44 
  45 /* clocks in AO (always on) controller */
  46 static const struct stratix10_pll_clock s10_pll_clks[] = {
  47         { STRATIX10_BOOT_CLK, "boot_clk", boot_mux, ARRAY_SIZE(boot_mux), 0,
  48           0x0},
  49         { STRATIX10_MAIN_PLL_CLK, "main_pll", pll_mux, ARRAY_SIZE(pll_mux),
  50           0, 0x74},
  51         { STRATIX10_PERIPH_PLL_CLK, "periph_pll", pll_mux, ARRAY_SIZE(pll_mux),
  52           0, 0xe4},
  53 };
  54 
  55 static const struct stratix10_perip_c_clock s10_main_perip_c_clks[] = {
  56         { STRATIX10_MAIN_MPU_BASE_CLK, "main_mpu_base_clk", "main_pll", NULL, 1, 0, 0x84},
  57         { STRATIX10_MAIN_NOC_BASE_CLK, "main_noc_base_clk", "main_pll", NULL, 1, 0, 0x88},
  58         { STRATIX10_PERI_MPU_BASE_CLK, "peri_mpu_base_clk", "periph_pll", NULL, 1, 0,
  59           0xF4},
  60         { STRATIX10_PERI_NOC_BASE_CLK, "peri_noc_base_clk", "periph_pll", NULL, 1, 0,
  61           0xF8},
  62 };
  63 
  64 static const struct stratix10_perip_cnt_clock s10_main_perip_cnt_clks[] = {
  65         { STRATIX10_MPU_FREE_CLK, "mpu_free_clk", NULL, mpu_free_mux, ARRAY_SIZE(mpu_free_mux),
  66            0, 0x48, 0, 0, 0},
  67         { STRATIX10_NOC_FREE_CLK, "noc_free_clk", NULL, noc_free_mux, ARRAY_SIZE(noc_free_mux),
  68           0, 0x4C, 0, 0, 0},
  69         { STRATIX10_MAIN_EMACA_CLK, "main_emaca_clk", "main_noc_base_clk", NULL, 1, 0,
  70           0x50, 0, 0, 0},
  71         { STRATIX10_MAIN_EMACB_CLK, "main_emacb_clk", "main_noc_base_clk", NULL, 1, 0,
  72           0x54, 0, 0, 0},
  73         { STRATIX10_MAIN_EMAC_PTP_CLK, "main_emac_ptp_clk", "main_noc_base_clk", NULL, 1, 0,
  74           0x58, 0, 0, 0},
  75         { STRATIX10_MAIN_GPIO_DB_CLK, "main_gpio_db_clk", "main_noc_base_clk", NULL, 1, 0,
  76           0x5C, 0, 0, 0},
  77         { STRATIX10_MAIN_SDMMC_CLK, "main_sdmmc_clk", "main_noc_base_clk", NULL, 1, 0,
  78           0x60, 0, 0, 0},
  79         { STRATIX10_MAIN_S2F_USR0_CLK, "main_s2f_usr0_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
  80           0, 0x64, 0, 0, 0},
  81         { STRATIX10_MAIN_S2F_USR1_CLK, "main_s2f_usr1_clk", "main_noc_base_clk", NULL, 1, 0,
  82           0x68, 0, 0, 0},
  83         { STRATIX10_MAIN_PSI_REF_CLK, "main_psi_ref_clk", "main_noc_base_clk", NULL, 1, 0,
  84           0x6C, 0, 0, 0},
  85         { STRATIX10_PERI_EMACA_CLK, "peri_emaca_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
  86           0, 0xBC, 0, 0, 0},
  87         { STRATIX10_PERI_EMACB_CLK, "peri_emacb_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
  88           0, 0xC0, 0, 0, 0},
  89         { STRATIX10_PERI_EMAC_PTP_CLK, "peri_emac_ptp_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
  90           0, 0xC4, 0, 0, 0},
  91         { STRATIX10_PERI_GPIO_DB_CLK, "peri_gpio_db_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
  92           0, 0xC8, 0, 0, 0},
  93         { STRATIX10_PERI_SDMMC_CLK, "peri_sdmmc_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
  94           0, 0xCC, 0, 0, 0},
  95         { STRATIX10_PERI_S2F_USR0_CLK, "peri_s2f_usr0_clk", "peri_noc_base_clk", NULL, 1, 0,
  96           0xD0, 0, 0, 0},
  97         { STRATIX10_PERI_S2F_USR1_CLK, "peri_s2f_usr1_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
  98           0, 0xD4, 0, 0, 0},
  99         { STRATIX10_PERI_PSI_REF_CLK, "peri_psi_ref_clk", "peri_noc_base_clk", NULL, 1, 0,
 100           0xD8, 0, 0, 0},
 101         { STRATIX10_L4_SYS_FREE_CLK, "l4_sys_free_clk", "noc_free_clk", NULL, 1, 0,
 102           0, 4, 0, 0},
 103         { STRATIX10_NOC_CLK, "noc_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux),
 104           0, 0, 0, 0x3C, 1},
 105         { STRATIX10_EMAC_A_FREE_CLK, "emaca_free_clk", NULL, emaca_free_mux, ARRAY_SIZE(emaca_free_mux),
 106           0, 0, 2, 0xB0, 0},
 107         { STRATIX10_EMAC_B_FREE_CLK, "emacb_free_clk", NULL, emacb_free_mux, ARRAY_SIZE(emacb_free_mux),
 108           0, 0, 2, 0xB0, 1},
 109         { STRATIX10_EMAC_PTP_FREE_CLK, "emac_ptp_free_clk", NULL, emac_ptp_free_mux,
 110           ARRAY_SIZE(emac_ptp_free_mux), 0, 0, 4, 0xB0, 2},
 111         { STRATIX10_GPIO_DB_FREE_CLK, "gpio_db_free_clk", NULL, gpio_db_free_mux,
 112           ARRAY_SIZE(gpio_db_free_mux), 0, 0, 0, 0xB0, 3},
 113         { STRATIX10_SDMMC_FREE_CLK, "sdmmc_free_clk", NULL, sdmmc_free_mux,
 114           ARRAY_SIZE(sdmmc_free_mux), 0, 0, 0, 0xB0, 4},
 115         { STRATIX10_S2F_USER1_FREE_CLK, "s2f_user1_free_clk", NULL, s2f_usr1_free_mux,
 116           ARRAY_SIZE(s2f_usr1_free_mux), 0, 0, 0, 0xB0, 5},
 117         { STRATIX10_PSI_REF_FREE_CLK, "psi_ref_free_clk", NULL, psi_ref_free_mux,
 118           ARRAY_SIZE(psi_ref_free_mux), 0, 0, 0, 0xB0, 6},
 119 };
 120 
 121 static const struct stratix10_gate_clock s10_gate_clks[] = {
 122         { STRATIX10_MPU_CLK, "mpu_clk", NULL, mpu_mux, ARRAY_SIZE(mpu_mux), 0, 0x30,
 123           0, 0, 0, 0, 0x3C, 0, 0},
 124         { STRATIX10_MPU_PERIPH_CLK, "mpu_periph_clk", "mpu_clk", NULL, 1, 0, 0x30,
 125           0, 0, 0, 0, 0, 0, 4},
 126         { STRATIX10_MPU_L2RAM_CLK, "mpu_l2ram_clk", "mpu_clk", NULL, 1, 0, 0x30,
 127           0, 0, 0, 0, 0, 0, 2},
 128         { STRATIX10_L4_MAIN_CLK, "l4_main_clk", "noc_clk", NULL, 1, 0, 0x30,
 129           1, 0x70, 0, 2, 0, 0, 0},
 130         { STRATIX10_L4_MP_CLK, "l4_mp_clk", "noc_clk", NULL, 1, 0, 0x30,
 131           2, 0x70, 8, 2, 0, 0, 0},
 132         { STRATIX10_L4_SP_CLK, "l4_sp_clk", "noc_clk", NULL, 1, CLK_IS_CRITICAL, 0x30,
 133           3, 0x70, 16, 2, 0, 0, 0},
 134         { STRATIX10_CS_AT_CLK, "cs_at_clk", "noc_clk", NULL, 1, 0, 0x30,
 135           4, 0x70, 24, 2, 0, 0, 0},
 136         { STRATIX10_CS_TRACE_CLK, "cs_trace_clk", "noc_clk", NULL, 1, 0, 0x30,
 137           4, 0x70, 26, 2, 0, 0, 0},
 138         { STRATIX10_CS_PDBG_CLK, "cs_pdbg_clk", "cs_at_clk", NULL, 1, 0, 0x30,
 139           4, 0x70, 28, 1, 0, 0, 0},
 140         { STRATIX10_CS_TIMER_CLK, "cs_timer_clk", "noc_clk", NULL, 1, 0, 0x30,
 141           5, 0, 0, 0, 0, 0, 0},
 142         { STRATIX10_S2F_USER0_CLK, "s2f_user0_clk", NULL, s2f_usr0_mux, ARRAY_SIZE(s2f_usr0_mux), 0, 0x30,
 143           6, 0, 0, 0, 0, 0, 0},
 144         { STRATIX10_EMAC0_CLK, "emac0_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
 145           0, 0, 0, 0, 0xDC, 26, 0},
 146         { STRATIX10_EMAC1_CLK, "emac1_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
 147           1, 0, 0, 0, 0xDC, 27, 0},
 148         { STRATIX10_EMAC2_CLK, "emac2_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
 149           2, 0, 0, 0, 0xDC, 28, 0},
 150         { STRATIX10_EMAC_PTP_CLK, "emac_ptp_clk", "emac_ptp_free_clk", NULL, 1, 0, 0xA4,
 151           3, 0, 0, 0, 0, 0, 0},
 152         { STRATIX10_GPIO_DB_CLK, "gpio_db_clk", "gpio_db_free_clk", NULL, 1, 0, 0xA4,
 153           4, 0xE0, 0, 16, 0, 0, 0},
 154         { STRATIX10_SDMMC_CLK, "sdmmc_clk", "sdmmc_free_clk", NULL, 1, 0, 0xA4,
 155           5, 0, 0, 0, 0, 0, 4},
 156         { STRATIX10_S2F_USER1_CLK, "s2f_user1_clk", "s2f_user1_free_clk", NULL, 1, 0, 0xA4,
 157           6, 0, 0, 0, 0, 0, 0},
 158         { STRATIX10_PSI_REF_CLK, "psi_ref_clk", "psi_ref_free_clk", NULL, 1, 0, 0xA4,
 159           7, 0, 0, 0, 0, 0, 0},
 160         { STRATIX10_USB_CLK, "usb_clk", "l4_mp_clk", NULL, 1, 0, 0xA4,
 161           8, 0, 0, 0, 0, 0, 0},
 162         { STRATIX10_SPI_M_CLK, "spi_m_clk", "l4_mp_clk", NULL, 1, 0, 0xA4,
 163           9, 0, 0, 0, 0, 0, 0},
 164         { STRATIX10_NAND_X_CLK, "nand_x_clk", "l4_mp_clk", NULL, 1, 0, 0xA4,
 165           10, 0, 0, 0, 0, 0, 0},
 166         { STRATIX10_NAND_CLK, "nand_clk", "nand_x_clk", NULL, 1, 0, 0xA4,
 167           10, 0, 0, 0, 0, 0, 4},
 168         { STRATIX10_NAND_ECC_CLK, "nand_ecc_clk", "nand_x_clk", NULL, 1, 0, 0xA4,
 169           10, 0, 0, 0, 0, 0, 4},
 170 };
 171 
 172 static int s10_clk_register_c_perip(const struct stratix10_perip_c_clock *clks,
 173                                     int nums, struct stratix10_clock_data *data)
 174 {
 175         struct clk *clk;
 176         void __iomem *base = data->base;
 177         int i;
 178 
 179         for (i = 0; i < nums; i++) {
 180                 clk = s10_register_periph(clks[i].name, clks[i].parent_name,
 181                                           clks[i].parent_names, clks[i].num_parents,
 182                                           clks[i].flags, base, clks[i].offset);
 183                 if (IS_ERR(clk)) {
 184                         pr_err("%s: failed to register clock %s\n",
 185                                __func__, clks[i].name);
 186                         continue;
 187                 }
 188                 data->clk_data.clks[clks[i].id] = clk;
 189         }
 190         return 0;
 191 }
 192 
 193 static int s10_clk_register_cnt_perip(const struct stratix10_perip_cnt_clock *clks,
 194                                       int nums, struct stratix10_clock_data *data)
 195 {
 196         struct clk *clk;
 197         void __iomem *base = data->base;
 198         int i;
 199 
 200         for (i = 0; i < nums; i++) {
 201                 clk = s10_register_cnt_periph(clks[i].name, clks[i].parent_name,
 202                                               clks[i].parent_names,
 203                                               clks[i].num_parents,
 204                                               clks[i].flags, base,
 205                                               clks[i].offset,
 206                                               clks[i].fixed_divider,
 207                                               clks[i].bypass_reg,
 208                                               clks[i].bypass_shift);
 209                 if (IS_ERR(clk)) {
 210                         pr_err("%s: failed to register clock %s\n",
 211                                __func__, clks[i].name);
 212                         continue;
 213                 }
 214                 data->clk_data.clks[clks[i].id] = clk;
 215         }
 216 
 217         return 0;
 218 }
 219 
 220 static int s10_clk_register_gate(const struct stratix10_gate_clock *clks,
 221                                  int nums, struct stratix10_clock_data *data)
 222 {
 223         struct clk *clk;
 224         void __iomem *base = data->base;
 225         int i;
 226 
 227         for (i = 0; i < nums; i++) {
 228                 clk = s10_register_gate(clks[i].name, clks[i].parent_name,
 229                                         clks[i].parent_names,
 230                                         clks[i].num_parents,
 231                                         clks[i].flags, base,
 232                                         clks[i].gate_reg,
 233                                         clks[i].gate_idx, clks[i].div_reg,
 234                                         clks[i].div_offset, clks[i].div_width,
 235                                         clks[i].bypass_reg,
 236                                         clks[i].bypass_shift,
 237                                         clks[i].fixed_div);
 238                 if (IS_ERR(clk)) {
 239                         pr_err("%s: failed to register clock %s\n",
 240                                __func__, clks[i].name);
 241                         continue;
 242                 }
 243                 data->clk_data.clks[clks[i].id] = clk;
 244         }
 245 
 246         return 0;
 247 }
 248 
 249 static int s10_clk_register_pll(const struct stratix10_pll_clock *clks,
 250                                  int nums, struct stratix10_clock_data *data)
 251 {
 252         struct clk *clk;
 253         void __iomem *base = data->base;
 254         int i;
 255 
 256         for (i = 0; i < nums; i++) {
 257                 clk = s10_register_pll(clks[i].name, clks[i].parent_names,
 258                                     clks[i].num_parents,
 259                                     clks[i].flags, base,
 260                                     clks[i].offset);
 261                 if (IS_ERR(clk)) {
 262                         pr_err("%s: failed to register clock %s\n",
 263                                __func__, clks[i].name);
 264                         continue;
 265                 }
 266                 data->clk_data.clks[clks[i].id] = clk;
 267         }
 268 
 269         return 0;
 270 }
 271 
 272 static struct stratix10_clock_data *__socfpga_s10_clk_init(struct platform_device *pdev,
 273                                                     int nr_clks)
 274 {
 275         struct device_node *np = pdev->dev.of_node;
 276         struct device *dev = &pdev->dev;
 277         struct stratix10_clock_data *clk_data;
 278         struct clk **clk_table;
 279         struct resource *res;
 280         void __iomem *base;
 281 
 282         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 283         base = devm_ioremap_resource(dev, res);
 284         if (IS_ERR(base)) {
 285                 pr_err("%s: failed to map clock registers\n", __func__);
 286                 return ERR_CAST(base);
 287         }
 288 
 289         clk_data = devm_kzalloc(dev, sizeof(*clk_data), GFP_KERNEL);
 290         if (!clk_data)
 291                 return ERR_PTR(-ENOMEM);
 292 
 293         clk_data->base = base;
 294         clk_table = devm_kcalloc(dev, nr_clks, sizeof(*clk_table), GFP_KERNEL);
 295         if (!clk_table)
 296                 return ERR_PTR(-ENOMEM);
 297 
 298         clk_data->clk_data.clks = clk_table;
 299         clk_data->clk_data.clk_num = nr_clks;
 300         of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data->clk_data);
 301         return clk_data;
 302 }
 303 
 304 static int s10_clkmgr_init(struct platform_device *pdev)
 305 {
 306         struct stratix10_clock_data *clk_data;
 307 
 308         clk_data = __socfpga_s10_clk_init(pdev, STRATIX10_NUM_CLKS);
 309         if (IS_ERR(clk_data))
 310                 return PTR_ERR(clk_data);
 311 
 312         s10_clk_register_pll(s10_pll_clks, ARRAY_SIZE(s10_pll_clks), clk_data);
 313 
 314         s10_clk_register_c_perip(s10_main_perip_c_clks,
 315                                  ARRAY_SIZE(s10_main_perip_c_clks), clk_data);
 316 
 317         s10_clk_register_cnt_perip(s10_main_perip_cnt_clks,
 318                                    ARRAY_SIZE(s10_main_perip_cnt_clks),
 319                                    clk_data);
 320 
 321         s10_clk_register_gate(s10_gate_clks, ARRAY_SIZE(s10_gate_clks),
 322                               clk_data);
 323         return 0;
 324 }
 325 
 326 static int s10_clkmgr_probe(struct platform_device *pdev)
 327 {
 328         return  s10_clkmgr_init(pdev);
 329 }
 330 
 331 static const struct of_device_id stratix10_clkmgr_match_table[] = {
 332         { .compatible = "intel,stratix10-clkmgr",
 333           .data = s10_clkmgr_init },
 334         { }
 335 };
 336 
 337 static struct platform_driver stratix10_clkmgr_driver = {
 338         .probe          = s10_clkmgr_probe,
 339         .driver         = {
 340                 .name   = "stratix10-clkmgr",
 341                 .suppress_bind_attrs = true,
 342                 .of_match_table = stratix10_clkmgr_match_table,
 343         },
 344 };
 345 
 346 static int __init s10_clk_init(void)
 347 {
 348         return platform_driver_register(&stratix10_clkmgr_driver);
 349 }
 350 core_initcall(s10_clk_init);

/* [<][>][^][v][top][bottom][index][help] */