279 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2// Copyright (C) 2015 Broadcom Corporation3 4#include <linux/kernel.h>5#include <linux/err.h>6#include <linux/clk-provider.h>7#include <linux/io.h>8#include <linux/of.h>9#include <linux/of_address.h>10 11#include <dt-bindings/clock/bcm-ns2.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 RESET_VAL(o, rs, prs) { .offset = o, .reset_shift = rs, \20 .p_reset_shift = prs }21 22#define DF_VAL(o, kis, kiw, kps, kpw, kas, kaw) { .offset = o, .ki_shift = kis,\23 .ki_width = kiw, .kp_shift = kps, .kp_width = kpw, .ka_shift = kas, \24 .ka_width = kaw }25 26#define VCO_CTRL_VAL(uo, lo) { .u_offset = uo, .l_offset = lo }27 28#define ENABLE_VAL(o, es, hs, bs) { .offset = o, .enable_shift = es, \29 .hold_shift = hs, .bypass_shift = bs }30 31static const struct iproc_pll_ctrl genpll_scr = {32 .flags = IPROC_CLK_AON | IPROC_CLK_PLL_SPLIT_STAT_CTRL,33 .aon = AON_VAL(0x0, 1, 15, 12),34 .reset = RESET_VAL(0x4, 2, 1),35 .dig_filter = DF_VAL(0x0, 9, 3, 5, 4, 2, 3),36 .ndiv_int = REG_VAL(0x8, 4, 10),37 .pdiv = REG_VAL(0x8, 0, 4),38 .vco_ctrl = VCO_CTRL_VAL(0x10, 0xc),39 .status = REG_VAL(0x0, 27, 1),40};41 42 43static const struct iproc_clk_ctrl genpll_scr_clk[] = {44 /* bypass_shift, the last value passed into ENABLE_VAL(), is not defined45 * in NS2. However, it doesn't appear to be used anywhere, so setting46 * it to 0.47 */48 [BCM_NS2_GENPLL_SCR_SCR_CLK] = {49 .channel = BCM_NS2_GENPLL_SCR_SCR_CLK,50 .flags = IPROC_CLK_AON,51 .enable = ENABLE_VAL(0x0, 18, 12, 0),52 .mdiv = REG_VAL(0x18, 0, 8),53 },54 [BCM_NS2_GENPLL_SCR_FS_CLK] = {55 .channel = BCM_NS2_GENPLL_SCR_FS_CLK,56 .flags = IPROC_CLK_AON,57 .enable = ENABLE_VAL(0x0, 19, 13, 0),58 .mdiv = REG_VAL(0x18, 8, 8),59 },60 [BCM_NS2_GENPLL_SCR_AUDIO_CLK] = {61 .channel = BCM_NS2_GENPLL_SCR_AUDIO_CLK,62 .flags = IPROC_CLK_AON,63 .enable = ENABLE_VAL(0x0, 20, 14, 0),64 .mdiv = REG_VAL(0x14, 0, 8),65 },66 [BCM_NS2_GENPLL_SCR_CH3_UNUSED] = {67 .channel = BCM_NS2_GENPLL_SCR_CH3_UNUSED,68 .flags = IPROC_CLK_AON,69 .enable = ENABLE_VAL(0x0, 21, 15, 0),70 .mdiv = REG_VAL(0x14, 8, 8),71 },72 [BCM_NS2_GENPLL_SCR_CH4_UNUSED] = {73 .channel = BCM_NS2_GENPLL_SCR_CH4_UNUSED,74 .flags = IPROC_CLK_AON,75 .enable = ENABLE_VAL(0x0, 22, 16, 0),76 .mdiv = REG_VAL(0x14, 16, 8),77 },78 [BCM_NS2_GENPLL_SCR_CH5_UNUSED] = {79 .channel = BCM_NS2_GENPLL_SCR_CH5_UNUSED,80 .flags = IPROC_CLK_AON,81 .enable = ENABLE_VAL(0x0, 23, 17, 0),82 .mdiv = REG_VAL(0x14, 24, 8),83 },84};85 86static void __init ns2_genpll_scr_clk_init(struct device_node *node)87{88 iproc_pll_clk_setup(node, &genpll_scr, NULL, 0, genpll_scr_clk,89 ARRAY_SIZE(genpll_scr_clk));90}91CLK_OF_DECLARE(ns2_genpll_src_clk, "brcm,ns2-genpll-scr",92 ns2_genpll_scr_clk_init);93 94static const struct iproc_pll_ctrl genpll_sw = {95 .flags = IPROC_CLK_AON | IPROC_CLK_PLL_SPLIT_STAT_CTRL,96 .aon = AON_VAL(0x0, 1, 11, 10),97 .reset = RESET_VAL(0x4, 2, 1),98 .dig_filter = DF_VAL(0x0, 9, 3, 5, 4, 2, 3),99 .ndiv_int = REG_VAL(0x8, 4, 10),100 .pdiv = REG_VAL(0x8, 0, 4),101 .vco_ctrl = VCO_CTRL_VAL(0x10, 0xc),102 .status = REG_VAL(0x0, 13, 1),103};104 105static const struct iproc_clk_ctrl genpll_sw_clk[] = {106 /* bypass_shift, the last value passed into ENABLE_VAL(), is not defined107 * in NS2. However, it doesn't appear to be used anywhere, so setting108 * it to 0.109 */110 [BCM_NS2_GENPLL_SW_RPE_CLK] = {111 .channel = BCM_NS2_GENPLL_SW_RPE_CLK,112 .flags = IPROC_CLK_AON,113 .enable = ENABLE_VAL(0x0, 18, 12, 0),114 .mdiv = REG_VAL(0x18, 0, 8),115 },116 [BCM_NS2_GENPLL_SW_250_CLK] = {117 .channel = BCM_NS2_GENPLL_SW_250_CLK,118 .flags = IPROC_CLK_AON,119 .enable = ENABLE_VAL(0x0, 19, 13, 0),120 .mdiv = REG_VAL(0x18, 8, 8),121 },122 [BCM_NS2_GENPLL_SW_NIC_CLK] = {123 .channel = BCM_NS2_GENPLL_SW_NIC_CLK,124 .flags = IPROC_CLK_AON,125 .enable = ENABLE_VAL(0x0, 20, 14, 0),126 .mdiv = REG_VAL(0x14, 0, 8),127 },128 [BCM_NS2_GENPLL_SW_CHIMP_CLK] = {129 .channel = BCM_NS2_GENPLL_SW_CHIMP_CLK,130 .flags = IPROC_CLK_AON,131 .enable = ENABLE_VAL(0x0, 21, 15, 0),132 .mdiv = REG_VAL(0x14, 8, 8),133 },134 [BCM_NS2_GENPLL_SW_PORT_CLK] = {135 .channel = BCM_NS2_GENPLL_SW_PORT_CLK,136 .flags = IPROC_CLK_AON,137 .enable = ENABLE_VAL(0x0, 22, 16, 0),138 .mdiv = REG_VAL(0x14, 16, 8),139 },140 [BCM_NS2_GENPLL_SW_SDIO_CLK] = {141 .channel = BCM_NS2_GENPLL_SW_SDIO_CLK,142 .flags = IPROC_CLK_AON,143 .enable = ENABLE_VAL(0x0, 23, 17, 0),144 .mdiv = REG_VAL(0x14, 24, 8),145 },146};147 148static void __init ns2_genpll_sw_clk_init(struct device_node *node)149{150 iproc_pll_clk_setup(node, &genpll_sw, NULL, 0, genpll_sw_clk,151 ARRAY_SIZE(genpll_sw_clk));152}153CLK_OF_DECLARE(ns2_genpll_sw_clk, "brcm,ns2-genpll-sw",154 ns2_genpll_sw_clk_init);155 156static const struct iproc_pll_ctrl lcpll_ddr = {157 .flags = IPROC_CLK_AON | IPROC_CLK_PLL_SPLIT_STAT_CTRL,158 .aon = AON_VAL(0x0, 2, 1, 0),159 .reset = RESET_VAL(0x4, 2, 1),160 .dig_filter = DF_VAL(0x0, 9, 3, 5, 4, 1, 4),161 .ndiv_int = REG_VAL(0x8, 4, 10),162 .pdiv = REG_VAL(0x8, 0, 4),163 .vco_ctrl = VCO_CTRL_VAL(0x10, 0xc),164 .status = REG_VAL(0x0, 0, 1),165};166 167static const struct iproc_clk_ctrl lcpll_ddr_clk[] = {168 /* bypass_shift, the last value passed into ENABLE_VAL(), is not defined169 * in NS2. However, it doesn't appear to be used anywhere, so setting170 * it to 0.171 */172 [BCM_NS2_LCPLL_DDR_PCIE_SATA_USB_CLK] = {173 .channel = BCM_NS2_LCPLL_DDR_PCIE_SATA_USB_CLK,174 .flags = IPROC_CLK_AON,175 .enable = ENABLE_VAL(0x0, 18, 12, 0),176 .mdiv = REG_VAL(0x14, 0, 8),177 },178 [BCM_NS2_LCPLL_DDR_DDR_CLK] = {179 .channel = BCM_NS2_LCPLL_DDR_DDR_CLK,180 .flags = IPROC_CLK_AON,181 .enable = ENABLE_VAL(0x0, 19, 13, 0),182 .mdiv = REG_VAL(0x14, 8, 8),183 },184 [BCM_NS2_LCPLL_DDR_CH2_UNUSED] = {185 .channel = BCM_NS2_LCPLL_DDR_CH2_UNUSED,186 .flags = IPROC_CLK_AON,187 .enable = ENABLE_VAL(0x0, 20, 14, 0),188 .mdiv = REG_VAL(0x10, 0, 8),189 },190 [BCM_NS2_LCPLL_DDR_CH3_UNUSED] = {191 .channel = BCM_NS2_LCPLL_DDR_CH3_UNUSED,192 .flags = IPROC_CLK_AON,193 .enable = ENABLE_VAL(0x0, 21, 15, 0),194 .mdiv = REG_VAL(0x10, 8, 8),195 },196 [BCM_NS2_LCPLL_DDR_CH4_UNUSED] = {197 .channel = BCM_NS2_LCPLL_DDR_CH4_UNUSED,198 .flags = IPROC_CLK_AON,199 .enable = ENABLE_VAL(0x0, 22, 16, 0),200 .mdiv = REG_VAL(0x10, 16, 8),201 },202 [BCM_NS2_LCPLL_DDR_CH5_UNUSED] = {203 .channel = BCM_NS2_LCPLL_DDR_CH5_UNUSED,204 .flags = IPROC_CLK_AON,205 .enable = ENABLE_VAL(0x0, 23, 17, 0),206 .mdiv = REG_VAL(0x10, 24, 8),207 },208};209 210static void __init ns2_lcpll_ddr_clk_init(struct device_node *node)211{212 iproc_pll_clk_setup(node, &lcpll_ddr, NULL, 0, lcpll_ddr_clk,213 ARRAY_SIZE(lcpll_ddr_clk));214}215CLK_OF_DECLARE(ns2_lcpll_ddr_clk, "brcm,ns2-lcpll-ddr",216 ns2_lcpll_ddr_clk_init);217 218static const struct iproc_pll_ctrl lcpll_ports = {219 .flags = IPROC_CLK_AON | IPROC_CLK_PLL_SPLIT_STAT_CTRL,220 .aon = AON_VAL(0x0, 2, 5, 4),221 .reset = RESET_VAL(0x4, 2, 1),222 .dig_filter = DF_VAL(0x0, 9, 3, 5, 4, 1, 4),223 .ndiv_int = REG_VAL(0x8, 4, 10),224 .pdiv = REG_VAL(0x8, 0, 4),225 .vco_ctrl = VCO_CTRL_VAL(0x10, 0xc),226 .status = REG_VAL(0x0, 0, 1),227};228 229static const struct iproc_clk_ctrl lcpll_ports_clk[] = {230 /* bypass_shift, the last value passed into ENABLE_VAL(), is not defined231 * in NS2. However, it doesn't appear to be used anywhere, so setting232 * it to 0.233 */234 [BCM_NS2_LCPLL_PORTS_WAN_CLK] = {235 .channel = BCM_NS2_LCPLL_PORTS_WAN_CLK,236 .flags = IPROC_CLK_AON,237 .enable = ENABLE_VAL(0x0, 18, 12, 0),238 .mdiv = REG_VAL(0x14, 0, 8),239 },240 [BCM_NS2_LCPLL_PORTS_RGMII_CLK] = {241 .channel = BCM_NS2_LCPLL_PORTS_RGMII_CLK,242 .flags = IPROC_CLK_AON,243 .enable = ENABLE_VAL(0x0, 19, 13, 0),244 .mdiv = REG_VAL(0x14, 8, 8),245 },246 [BCM_NS2_LCPLL_PORTS_CH2_UNUSED] = {247 .channel = BCM_NS2_LCPLL_PORTS_CH2_UNUSED,248 .flags = IPROC_CLK_AON,249 .enable = ENABLE_VAL(0x0, 20, 14, 0),250 .mdiv = REG_VAL(0x10, 0, 8),251 },252 [BCM_NS2_LCPLL_PORTS_CH3_UNUSED] = {253 .channel = BCM_NS2_LCPLL_PORTS_CH3_UNUSED,254 .flags = IPROC_CLK_AON,255 .enable = ENABLE_VAL(0x0, 21, 15, 0),256 .mdiv = REG_VAL(0x10, 8, 8),257 },258 [BCM_NS2_LCPLL_PORTS_CH4_UNUSED] = {259 .channel = BCM_NS2_LCPLL_PORTS_CH4_UNUSED,260 .flags = IPROC_CLK_AON,261 .enable = ENABLE_VAL(0x0, 22, 16, 0),262 .mdiv = REG_VAL(0x10, 16, 8),263 },264 [BCM_NS2_LCPLL_PORTS_CH5_UNUSED] = {265 .channel = BCM_NS2_LCPLL_PORTS_CH5_UNUSED,266 .flags = IPROC_CLK_AON,267 .enable = ENABLE_VAL(0x0, 23, 17, 0),268 .mdiv = REG_VAL(0x10, 24, 8),269 },270};271 272static void __init ns2_lcpll_ports_clk_init(struct device_node *node)273{274 iproc_pll_clk_setup(node, &lcpll_ports, NULL, 0, lcpll_ports_clk,275 ARRAY_SIZE(lcpll_ports_clk));276}277CLK_OF_DECLARE(ns2_lcpll_ports_clk, "brcm,ns2-lcpll-ports",278 ns2_lcpll_ports_clk_init);279