422 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright 2017 Broadcom4 */5 6#include <linux/err.h>7#include <linux/clk-provider.h>8#include <linux/of.h>9#include <linux/platform_device.h>10 11#include <dt-bindings/clock/bcm-sr.h>12#include "clk-iproc.h"13 14#define REG_VAL(o, s, w) { .offset = o, .shift = s, .width = w, }15 16#define AON_VAL(o, pw, ps, is) { .offset = o, .pwr_width = pw, \17 .pwr_shift = ps, .iso_shift = is }18 19#define SW_CTRL_VAL(o, s) { .offset = o, .shift = s, }20 21#define RESET_VAL(o, rs, prs) { .offset = o, .reset_shift = rs, \22 .p_reset_shift = prs }23 24#define DF_VAL(o, kis, kiw, kps, kpw, kas, kaw) { .offset = o, \25 .ki_shift = kis, .ki_width = kiw, .kp_shift = kps, .kp_width = kpw, \26 .ka_shift = kas, .ka_width = kaw }27 28#define VCO_CTRL_VAL(uo, lo) { .u_offset = uo, .l_offset = lo }29 30#define ENABLE_VAL(o, es, hs, bs) { .offset = o, .enable_shift = es, \31 .hold_shift = hs, .bypass_shift = bs }32 33 34static const struct iproc_pll_ctrl sr_genpll0 = {35 .flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC |36 IPROC_CLK_PLL_NEEDS_SW_CFG,37 .aon = AON_VAL(0x0, 5, 1, 0),38 .reset = RESET_VAL(0x0, 12, 11),39 .dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 3),40 .sw_ctrl = SW_CTRL_VAL(0x10, 31),41 .ndiv_int = REG_VAL(0x10, 20, 10),42 .ndiv_frac = REG_VAL(0x10, 0, 20),43 .pdiv = REG_VAL(0x14, 0, 4),44 .status = REG_VAL(0x30, 12, 1),45};46 47static const struct iproc_clk_ctrl sr_genpll0_clk[] = {48 [BCM_SR_GENPLL0_125M_CLK] = {49 .channel = BCM_SR_GENPLL0_125M_CLK,50 .flags = IPROC_CLK_AON,51 .enable = ENABLE_VAL(0x4, 6, 0, 12),52 .mdiv = REG_VAL(0x18, 0, 9),53 },54 [BCM_SR_GENPLL0_SCR_CLK] = {55 .channel = BCM_SR_GENPLL0_SCR_CLK,56 .flags = IPROC_CLK_AON,57 .enable = ENABLE_VAL(0x4, 7, 1, 13),58 .mdiv = REG_VAL(0x18, 10, 9),59 },60 [BCM_SR_GENPLL0_250M_CLK] = {61 .channel = BCM_SR_GENPLL0_250M_CLK,62 .flags = IPROC_CLK_AON,63 .enable = ENABLE_VAL(0x4, 8, 2, 14),64 .mdiv = REG_VAL(0x18, 20, 9),65 },66 [BCM_SR_GENPLL0_PCIE_AXI_CLK] = {67 .channel = BCM_SR_GENPLL0_PCIE_AXI_CLK,68 .flags = IPROC_CLK_AON,69 .enable = ENABLE_VAL(0x4, 9, 3, 15),70 .mdiv = REG_VAL(0x1c, 0, 9),71 },72 [BCM_SR_GENPLL0_PAXC_AXI_X2_CLK] = {73 .channel = BCM_SR_GENPLL0_PAXC_AXI_X2_CLK,74 .flags = IPROC_CLK_AON,75 .enable = ENABLE_VAL(0x4, 10, 4, 16),76 .mdiv = REG_VAL(0x1c, 10, 9),77 },78 [BCM_SR_GENPLL0_PAXC_AXI_CLK] = {79 .channel = BCM_SR_GENPLL0_PAXC_AXI_CLK,80 .flags = IPROC_CLK_AON,81 .enable = ENABLE_VAL(0x4, 11, 5, 17),82 .mdiv = REG_VAL(0x1c, 20, 9),83 },84};85 86static int sr_genpll0_clk_init(struct platform_device *pdev)87{88 iproc_pll_clk_setup(pdev->dev.of_node,89 &sr_genpll0, NULL, 0, sr_genpll0_clk,90 ARRAY_SIZE(sr_genpll0_clk));91 return 0;92}93 94static const struct iproc_pll_ctrl sr_genpll2 = {95 .flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC |96 IPROC_CLK_PLL_NEEDS_SW_CFG,97 .aon = AON_VAL(0x0, 1, 13, 12),98 .reset = RESET_VAL(0x0, 12, 11),99 .dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 3),100 .sw_ctrl = SW_CTRL_VAL(0x10, 31),101 .ndiv_int = REG_VAL(0x10, 20, 10),102 .ndiv_frac = REG_VAL(0x10, 0, 20),103 .pdiv = REG_VAL(0x14, 0, 4),104 .status = REG_VAL(0x30, 12, 1),105};106 107static const struct iproc_clk_ctrl sr_genpll2_clk[] = {108 [BCM_SR_GENPLL2_NIC_CLK] = {109 .channel = BCM_SR_GENPLL2_NIC_CLK,110 .flags = IPROC_CLK_AON,111 .enable = ENABLE_VAL(0x4, 6, 0, 12),112 .mdiv = REG_VAL(0x18, 0, 9),113 },114 [BCM_SR_GENPLL2_TS_500_CLK] = {115 .channel = BCM_SR_GENPLL2_TS_500_CLK,116 .flags = IPROC_CLK_AON,117 .enable = ENABLE_VAL(0x4, 7, 1, 13),118 .mdiv = REG_VAL(0x18, 10, 9),119 },120 [BCM_SR_GENPLL2_125_NITRO_CLK] = {121 .channel = BCM_SR_GENPLL2_125_NITRO_CLK,122 .flags = IPROC_CLK_AON,123 .enable = ENABLE_VAL(0x4, 8, 2, 14),124 .mdiv = REG_VAL(0x18, 20, 9),125 },126 [BCM_SR_GENPLL2_CHIMP_CLK] = {127 .channel = BCM_SR_GENPLL2_CHIMP_CLK,128 .flags = IPROC_CLK_AON,129 .enable = ENABLE_VAL(0x4, 9, 3, 15),130 .mdiv = REG_VAL(0x1c, 0, 9),131 },132 [BCM_SR_GENPLL2_NIC_FLASH_CLK] = {133 .channel = BCM_SR_GENPLL2_NIC_FLASH_CLK,134 .flags = IPROC_CLK_AON,135 .enable = ENABLE_VAL(0x4, 10, 4, 16),136 .mdiv = REG_VAL(0x1c, 10, 9),137 },138 [BCM_SR_GENPLL2_FS4_CLK] = {139 .channel = BCM_SR_GENPLL2_FS4_CLK,140 .enable = ENABLE_VAL(0x4, 11, 5, 17),141 .mdiv = REG_VAL(0x1c, 20, 9),142 },143};144 145static int sr_genpll2_clk_init(struct platform_device *pdev)146{147 iproc_pll_clk_setup(pdev->dev.of_node,148 &sr_genpll2, NULL, 0, sr_genpll2_clk,149 ARRAY_SIZE(sr_genpll2_clk));150 return 0;151}152 153static const struct iproc_pll_ctrl sr_genpll3 = {154 .flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC |155 IPROC_CLK_PLL_NEEDS_SW_CFG,156 .aon = AON_VAL(0x0, 1, 19, 18),157 .reset = RESET_VAL(0x0, 12, 11),158 .dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 3),159 .sw_ctrl = SW_CTRL_VAL(0x10, 31),160 .ndiv_int = REG_VAL(0x10, 20, 10),161 .ndiv_frac = REG_VAL(0x10, 0, 20),162 .pdiv = REG_VAL(0x14, 0, 4),163 .status = REG_VAL(0x30, 12, 1),164};165 166static const struct iproc_clk_ctrl sr_genpll3_clk[] = {167 [BCM_SR_GENPLL3_HSLS_CLK] = {168 .channel = BCM_SR_GENPLL3_HSLS_CLK,169 .flags = IPROC_CLK_AON,170 .enable = ENABLE_VAL(0x4, 6, 0, 12),171 .mdiv = REG_VAL(0x18, 0, 9),172 },173 [BCM_SR_GENPLL3_SDIO_CLK] = {174 .channel = BCM_SR_GENPLL3_SDIO_CLK,175 .flags = IPROC_CLK_AON,176 .enable = ENABLE_VAL(0x4, 7, 1, 13),177 .mdiv = REG_VAL(0x18, 10, 9),178 },179};180 181static void sr_genpll3_clk_init(struct device_node *node)182{183 iproc_pll_clk_setup(node, &sr_genpll3, NULL, 0, sr_genpll3_clk,184 ARRAY_SIZE(sr_genpll3_clk));185}186CLK_OF_DECLARE(sr_genpll3_clk, "brcm,sr-genpll3", sr_genpll3_clk_init);187 188static const struct iproc_pll_ctrl sr_genpll4 = {189 .flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC |190 IPROC_CLK_PLL_NEEDS_SW_CFG,191 .aon = AON_VAL(0x0, 1, 25, 24),192 .reset = RESET_VAL(0x0, 12, 11),193 .dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 3),194 .sw_ctrl = SW_CTRL_VAL(0x10, 31),195 .ndiv_int = REG_VAL(0x10, 20, 10),196 .ndiv_frac = REG_VAL(0x10, 0, 20),197 .pdiv = REG_VAL(0x14, 0, 4),198 .status = REG_VAL(0x30, 12, 1),199};200 201static const struct iproc_clk_ctrl sr_genpll4_clk[] = {202 [BCM_SR_GENPLL4_CCN_CLK] = {203 .channel = BCM_SR_GENPLL4_CCN_CLK,204 .flags = IPROC_CLK_AON,205 .enable = ENABLE_VAL(0x4, 6, 0, 12),206 .mdiv = REG_VAL(0x18, 0, 9),207 },208 [BCM_SR_GENPLL4_TPIU_PLL_CLK] = {209 .channel = BCM_SR_GENPLL4_TPIU_PLL_CLK,210 .flags = IPROC_CLK_AON,211 .enable = ENABLE_VAL(0x4, 7, 1, 13),212 .mdiv = REG_VAL(0x18, 10, 9),213 },214 [BCM_SR_GENPLL4_NOC_CLK] = {215 .channel = BCM_SR_GENPLL4_NOC_CLK,216 .flags = IPROC_CLK_AON,217 .enable = ENABLE_VAL(0x4, 8, 2, 14),218 .mdiv = REG_VAL(0x18, 20, 9),219 },220 [BCM_SR_GENPLL4_CHCLK_FS4_CLK] = {221 .channel = BCM_SR_GENPLL4_CHCLK_FS4_CLK,222 .flags = IPROC_CLK_AON,223 .enable = ENABLE_VAL(0x4, 9, 3, 15),224 .mdiv = REG_VAL(0x1c, 0, 9),225 },226 [BCM_SR_GENPLL4_BRIDGE_FSCPU_CLK] = {227 .channel = BCM_SR_GENPLL4_BRIDGE_FSCPU_CLK,228 .flags = IPROC_CLK_AON,229 .enable = ENABLE_VAL(0x4, 10, 4, 16),230 .mdiv = REG_VAL(0x1c, 10, 9),231 },232};233 234static int sr_genpll4_clk_init(struct platform_device *pdev)235{236 iproc_pll_clk_setup(pdev->dev.of_node,237 &sr_genpll4, NULL, 0, sr_genpll4_clk,238 ARRAY_SIZE(sr_genpll4_clk));239 return 0;240}241 242static const struct iproc_pll_ctrl sr_genpll5 = {243 .flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC |244 IPROC_CLK_PLL_NEEDS_SW_CFG,245 .aon = AON_VAL(0x0, 1, 1, 0),246 .reset = RESET_VAL(0x0, 12, 11),247 .dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 3),248 .sw_ctrl = SW_CTRL_VAL(0x10, 31),249 .ndiv_int = REG_VAL(0x10, 20, 10),250 .ndiv_frac = REG_VAL(0x10, 0, 20),251 .pdiv = REG_VAL(0x14, 0, 4),252 .status = REG_VAL(0x30, 12, 1),253};254 255static const struct iproc_clk_ctrl sr_genpll5_clk[] = {256 [BCM_SR_GENPLL5_FS4_HF_CLK] = {257 .channel = BCM_SR_GENPLL5_FS4_HF_CLK,258 .enable = ENABLE_VAL(0x4, 6, 0, 12),259 .mdiv = REG_VAL(0x18, 0, 9),260 },261 [BCM_SR_GENPLL5_CRYPTO_AE_CLK] = {262 .channel = BCM_SR_GENPLL5_CRYPTO_AE_CLK,263 .enable = ENABLE_VAL(0x4, 7, 1, 12),264 .mdiv = REG_VAL(0x18, 10, 9),265 },266 [BCM_SR_GENPLL5_RAID_AE_CLK] = {267 .channel = BCM_SR_GENPLL5_RAID_AE_CLK,268 .enable = ENABLE_VAL(0x4, 8, 2, 14),269 .mdiv = REG_VAL(0x18, 20, 9),270 },271};272 273static int sr_genpll5_clk_init(struct platform_device *pdev)274{275 iproc_pll_clk_setup(pdev->dev.of_node,276 &sr_genpll5, NULL, 0, sr_genpll5_clk,277 ARRAY_SIZE(sr_genpll5_clk));278 return 0;279}280 281static const struct iproc_pll_ctrl sr_lcpll0 = {282 .flags = IPROC_CLK_AON | IPROC_CLK_PLL_NEEDS_SW_CFG,283 .aon = AON_VAL(0x0, 2, 19, 18),284 .reset = RESET_VAL(0x0, 31, 30),285 .sw_ctrl = SW_CTRL_VAL(0x4, 31),286 .ndiv_int = REG_VAL(0x4, 16, 10),287 .pdiv = REG_VAL(0x4, 26, 4),288 .status = REG_VAL(0x38, 12, 1),289};290 291static const struct iproc_clk_ctrl sr_lcpll0_clk[] = {292 [BCM_SR_LCPLL0_SATA_REFP_CLK] = {293 .channel = BCM_SR_LCPLL0_SATA_REFP_CLK,294 .flags = IPROC_CLK_AON,295 .enable = ENABLE_VAL(0x0, 7, 1, 13),296 .mdiv = REG_VAL(0x14, 0, 9),297 },298 [BCM_SR_LCPLL0_SATA_REFN_CLK] = {299 .channel = BCM_SR_LCPLL0_SATA_REFN_CLK,300 .flags = IPROC_CLK_AON,301 .enable = ENABLE_VAL(0x0, 8, 2, 14),302 .mdiv = REG_VAL(0x14, 10, 9),303 },304 [BCM_SR_LCPLL0_SATA_350_CLK] = {305 .channel = BCM_SR_LCPLL0_SATA_350_CLK,306 .flags = IPROC_CLK_AON,307 .enable = ENABLE_VAL(0x0, 9, 3, 15),308 .mdiv = REG_VAL(0x14, 20, 9),309 },310 [BCM_SR_LCPLL0_SATA_500_CLK] = {311 .channel = BCM_SR_LCPLL0_SATA_500_CLK,312 .flags = IPROC_CLK_AON,313 .enable = ENABLE_VAL(0x0, 10, 4, 16),314 .mdiv = REG_VAL(0x18, 0, 9),315 },316};317 318static int sr_lcpll0_clk_init(struct platform_device *pdev)319{320 iproc_pll_clk_setup(pdev->dev.of_node,321 &sr_lcpll0, NULL, 0, sr_lcpll0_clk,322 ARRAY_SIZE(sr_lcpll0_clk));323 return 0;324}325 326static const struct iproc_pll_ctrl sr_lcpll1 = {327 .flags = IPROC_CLK_AON | IPROC_CLK_PLL_NEEDS_SW_CFG,328 .aon = AON_VAL(0x0, 2, 22, 21),329 .reset = RESET_VAL(0x0, 31, 30),330 .sw_ctrl = SW_CTRL_VAL(0x4, 31),331 .ndiv_int = REG_VAL(0x4, 16, 10),332 .pdiv = REG_VAL(0x4, 26, 4),333 .status = REG_VAL(0x38, 12, 1),334};335 336static const struct iproc_clk_ctrl sr_lcpll1_clk[] = {337 [BCM_SR_LCPLL1_WAN_CLK] = {338 .channel = BCM_SR_LCPLL1_WAN_CLK,339 .flags = IPROC_CLK_AON,340 .enable = ENABLE_VAL(0x0, 7, 1, 13),341 .mdiv = REG_VAL(0x14, 0, 9),342 },343 [BCM_SR_LCPLL1_USB_REF_CLK] = {344 .channel = BCM_SR_LCPLL1_USB_REF_CLK,345 .flags = IPROC_CLK_AON,346 .enable = ENABLE_VAL(0x0, 8, 2, 14),347 .mdiv = REG_VAL(0x14, 10, 9),348 },349 [BCM_SR_LCPLL1_CRMU_TS_CLK] = {350 .channel = BCM_SR_LCPLL1_CRMU_TS_CLK,351 .flags = IPROC_CLK_AON,352 .enable = ENABLE_VAL(0x0, 9, 3, 15),353 .mdiv = REG_VAL(0x14, 20, 9),354 },355};356 357static int sr_lcpll1_clk_init(struct platform_device *pdev)358{359 iproc_pll_clk_setup(pdev->dev.of_node,360 &sr_lcpll1, NULL, 0, sr_lcpll1_clk,361 ARRAY_SIZE(sr_lcpll1_clk));362 return 0;363}364 365static const struct iproc_pll_ctrl sr_lcpll_pcie = {366 .flags = IPROC_CLK_AON | IPROC_CLK_PLL_NEEDS_SW_CFG,367 .aon = AON_VAL(0x0, 2, 25, 24),368 .reset = RESET_VAL(0x0, 31, 30),369 .sw_ctrl = SW_CTRL_VAL(0x4, 31),370 .ndiv_int = REG_VAL(0x4, 16, 10),371 .pdiv = REG_VAL(0x4, 26, 4),372 .status = REG_VAL(0x38, 12, 1),373};374 375static const struct iproc_clk_ctrl sr_lcpll_pcie_clk[] = {376 [BCM_SR_LCPLL_PCIE_PHY_REF_CLK] = {377 .channel = BCM_SR_LCPLL_PCIE_PHY_REF_CLK,378 .flags = IPROC_CLK_AON,379 .enable = ENABLE_VAL(0x0, 7, 1, 13),380 .mdiv = REG_VAL(0x14, 0, 9),381 },382};383 384static int sr_lcpll_pcie_clk_init(struct platform_device *pdev)385{386 iproc_pll_clk_setup(pdev->dev.of_node,387 &sr_lcpll_pcie, NULL, 0, sr_lcpll_pcie_clk,388 ARRAY_SIZE(sr_lcpll_pcie_clk));389 return 0;390}391 392static const struct of_device_id sr_clk_dt_ids[] = {393 { .compatible = "brcm,sr-genpll0", .data = sr_genpll0_clk_init },394 { .compatible = "brcm,sr-genpll2", .data = sr_genpll2_clk_init },395 { .compatible = "brcm,sr-genpll4", .data = sr_genpll4_clk_init },396 { .compatible = "brcm,sr-genpll5", .data = sr_genpll5_clk_init },397 { .compatible = "brcm,sr-lcpll0", .data = sr_lcpll0_clk_init },398 { .compatible = "brcm,sr-lcpll1", .data = sr_lcpll1_clk_init },399 { .compatible = "brcm,sr-lcpll-pcie", .data = sr_lcpll_pcie_clk_init },400 { /* sentinel */ }401};402 403static int sr_clk_probe(struct platform_device *pdev)404{405 int (*probe_func)(struct platform_device *);406 407 probe_func = of_device_get_match_data(&pdev->dev);408 if (!probe_func)409 return -ENODEV;410 411 return probe_func(pdev);412}413 414static struct platform_driver sr_clk_driver = {415 .driver = {416 .name = "sr-clk",417 .of_match_table = sr_clk_dt_ids,418 },419 .probe = sr_clk_probe,420};421builtin_platform_driver(sr_clk_driver);422