aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Boyd <sboyd@codeaurora.org>2015-10-21 20:28:19 -0400
committerStephen Boyd <sboyd@codeaurora.org>2015-10-21 20:28:19 -0400
commitf63d19ef52aa66e97fca2425974845177ce02b0a (patch)
tree53ec668d90828b5a4144ef445df347e6fea19ae5
parent938ce30e29dcb8ca0b1bf375305485ed17f40062 (diff)
parent0064c862340626400a56d72e5e86f01ef0d5a498 (diff)
Merge branch 'clk-iproc' into clk-next
* clk-iproc: clk: iproc: define Broadcom NS2 iProc clock binding clk: iproc: define Broadcom NSP iProc clock binding clk: ns2: add clock support for Broadcom Northstar 2 SoC clk: iproc: Separate status and control variables clk: iproc: Split off dig_filter clk: iproc: Add PLL base write function clk: nsp: add clock support for Broadcom Northstar Plus SoC clk: iproc: Add PWRCTRL support clk: cygnus: Convert all macros to all caps ARM: cygnus: fix link failures when CONFIG_COMMON_CLK_IPROC is disabled
-rw-r--r--Documentation/devicetree/bindings/clock/brcm,iproc-clocks.txt78
-rw-r--r--arch/arm/mach-bcm/Kconfig2
-rw-r--r--drivers/clk/Makefile2
-rw-r--r--drivers/clk/bcm/Kconfig4
-rw-r--r--drivers/clk/bcm/Makefile3
-rw-r--r--drivers/clk/bcm/clk-cygnus.c155
-rw-r--r--drivers/clk/bcm/clk-iproc-pll.c183
-rw-r--r--drivers/clk/bcm/clk-iproc.h22
-rw-r--r--drivers/clk/bcm/clk-ns2.c288
-rw-r--r--drivers/clk/bcm/clk-nsp.c139
-rw-r--r--include/dt-bindings/clock/bcm-ns2.h72
-rw-r--r--include/dt-bindings/clock/bcm-nsp.h51
12 files changed, 840 insertions, 159 deletions
diff --git a/Documentation/devicetree/bindings/clock/brcm,iproc-clocks.txt b/Documentation/devicetree/bindings/clock/brcm,iproc-clocks.txt
index da8d9bb5751c..ede65a55e21b 100644
--- a/Documentation/devicetree/bindings/clock/brcm,iproc-clocks.txt
+++ b/Documentation/devicetree/bindings/clock/brcm,iproc-clocks.txt
@@ -130,3 +130,81 @@ These clock IDs are defined in:
130 ch3_unused mipipll 4 BCM_CYGNUS_MIPIPLL_CH3_UNUSED 130 ch3_unused mipipll 4 BCM_CYGNUS_MIPIPLL_CH3_UNUSED
131 ch4_unused mipipll 5 BCM_CYGNUS_MIPIPLL_CH4_UNUSED 131 ch4_unused mipipll 5 BCM_CYGNUS_MIPIPLL_CH4_UNUSED
132 ch5_unused mipipll 6 BCM_CYGNUS_MIPIPLL_CH5_UNUSED 132 ch5_unused mipipll 6 BCM_CYGNUS_MIPIPLL_CH5_UNUSED
133
134Northstar and Northstar Plus
135------
136PLL and leaf clock compatible strings for Northstar and Northstar Plus are:
137 "brcm,nsp-armpll"
138 "brcm,nsp-genpll"
139 "brcm,nsp-lcpll0"
140
141The following table defines the set of PLL/clock index and ID for Northstar and
142Northstar Plus. These clock IDs are defined in:
143 "include/dt-bindings/clock/bcm-nsp.h"
144
145 Clock Source Index ID
146 --- ----- ----- ---------
147 crystal N/A N/A N/A
148
149 armpll crystal N/A N/A
150
151 genpll crystal 0 BCM_NSP_GENPLL
152 phy genpll 1 BCM_NSP_GENPLL_PHY_CLK
153 ethernetclk genpll 2 BCM_NSP_GENPLL_ENET_SW_CLK
154 usbclk genpll 3 BCM_NSP_GENPLL_USB_PHY_REF_CLK
155 iprocfast genpll 4 BCM_NSP_GENPLL_IPROCFAST_CLK
156 sata1 genpll 5 BCM_NSP_GENPLL_SATA1_CLK
157 sata2 genpll 6 BCM_NSP_GENPLL_SATA2_CLK
158
159 lcpll0 crystal 0 BCM_NSP_LCPLL0
160 pcie_phy lcpll0 1 BCM_NSP_LCPLL0_PCIE_PHY_REF_CLK
161 sdio lcpll0 2 BCM_NSP_LCPLL0_SDIO_CLK
162 ddr_phy lcpll0 3 BCM_NSP_LCPLL0_DDR_PHY_CLK
163
164Northstar 2
165-----------
166PLL and leaf clock compatible strings for Northstar 2 are:
167 "brcm,ns2-genpll-scr"
168 "brcm,ns2-genpll-sw"
169 "brcm,ns2-lcpll-ddr"
170 "brcm,ns2-lcpll-ports"
171
172The following table defines the set of PLL/clock index and ID for Northstar 2.
173These clock IDs are defined in:
174 "include/dt-bindings/clock/bcm-ns2.h"
175
176 Clock Source Index ID
177 --- ----- ----- ---------
178 crystal N/A N/A N/A
179
180 genpll_scr crystal 0 BCM_NS2_GENPLL_SCR
181 scr genpll_scr 1 BCM_NS2_GENPLL_SCR_SCR_CLK
182 fs genpll_scr 2 BCM_NS2_GENPLL_SCR_FS_CLK
183 audio_ref genpll_scr 3 BCM_NS2_GENPLL_SCR_AUDIO_CLK
184 ch3_unused genpll_scr 4 BCM_NS2_GENPLL_SCR_CH3_UNUSED
185 ch4_unused genpll_scr 5 BCM_NS2_GENPLL_SCR_CH4_UNUSED
186 ch5_unused genpll_scr 6 BCM_NS2_GENPLL_SCR_CH5_UNUSED
187
188 genpll_sw crystal 0 BCM_NS2_GENPLL_SW
189 rpe genpll_sw 1 BCM_NS2_GENPLL_SW_RPE_CLK
190 250 genpll_sw 2 BCM_NS2_GENPLL_SW_250_CLK
191 nic genpll_sw 3 BCM_NS2_GENPLL_SW_NIC_CLK
192 chimp genpll_sw 4 BCM_NS2_GENPLL_SW_CHIMP_CLK
193 port genpll_sw 5 BCM_NS2_GENPLL_SW_PORT_CLK
194 sdio genpll_sw 6 BCM_NS2_GENPLL_SW_SDIO_CLK
195
196 lcpll_ddr crystal 0 BCM_NS2_LCPLL_DDR
197 pcie_sata_usb lcpll_ddr 1 BCM_NS2_LCPLL_DDR_PCIE_SATA_USB_CLK
198 ddr lcpll_ddr 2 BCM_NS2_LCPLL_DDR_DDR_CLK
199 ch2_unused lcpll_ddr 3 BCM_NS2_LCPLL_DDR_CH2_UNUSED
200 ch3_unused lcpll_ddr 4 BCM_NS2_LCPLL_DDR_CH3_UNUSED
201 ch4_unused lcpll_ddr 5 BCM_NS2_LCPLL_DDR_CH4_UNUSED
202 ch5_unused lcpll_ddr 6 BCM_NS2_LCPLL_DDR_CH5_UNUSED
203
204 lcpll_ports crystal 0 BCM_NS2_LCPLL_PORTS
205 wan lcpll_ports 1 BCM_NS2_LCPLL_PORTS_WAN_CLK
206 rgmii lcpll_ports 2 BCM_NS2_LCPLL_PORTS_RGMII_CLK
207 ch2_unused lcpll_ports 3 BCM_NS2_LCPLL_PORTS_CH2_UNUSED
208 ch3_unused lcpll_ports 4 BCM_NS2_LCPLL_PORTS_CH3_UNUSED
209 ch4_unused lcpll_ports 5 BCM_NS2_LCPLL_PORTS_CH4_UNUSED
210 ch5_unused lcpll_ports 6 BCM_NS2_LCPLL_PORTS_CH5_UNUSED
diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig
index 1319c3c14327..84bd26535ae9 100644
--- a/arch/arm/mach-bcm/Kconfig
+++ b/arch/arm/mach-bcm/Kconfig
@@ -14,7 +14,7 @@ config ARCH_BCM_IPROC
14 select HAVE_ARM_SCU if SMP 14 select HAVE_ARM_SCU if SMP
15 select HAVE_ARM_TWD if SMP 15 select HAVE_ARM_TWD if SMP
16 select ARM_GLOBAL_TIMER 16 select ARM_GLOBAL_TIMER
17 17 select COMMON_CLK_IPROC
18 select CLKSRC_MMIO 18 select CLKSRC_MMIO
19 select ARCH_REQUIRE_GPIOLIB 19 select ARCH_REQUIRE_GPIOLIB
20 select ARM_AMBA 20 select ARM_AMBA
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 58fd167c462a..d3e1910eebab 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -48,7 +48,7 @@ obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
48obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o 48obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o
49obj-$(CONFIG_COMMON_CLK_PWM) += clk-pwm.o 49obj-$(CONFIG_COMMON_CLK_PWM) += clk-pwm.o
50obj-$(CONFIG_COMMON_CLK_AT91) += at91/ 50obj-$(CONFIG_COMMON_CLK_AT91) += at91/
51obj-$(CONFIG_ARCH_BCM) += bcm/ 51obj-y += bcm/
52obj-$(CONFIG_ARCH_BERLIN) += berlin/ 52obj-$(CONFIG_ARCH_BERLIN) += berlin/
53obj-$(CONFIG_ARCH_HISI) += hisilicon/ 53obj-$(CONFIG_ARCH_HISI) += hisilicon/
54obj-$(CONFIG_ARCH_MXC) += imx/ 54obj-$(CONFIG_ARCH_MXC) += imx/
diff --git a/drivers/clk/bcm/Kconfig b/drivers/clk/bcm/Kconfig
index 561e9dc6d40d..85260fb96b36 100644
--- a/drivers/clk/bcm/Kconfig
+++ b/drivers/clk/bcm/Kconfig
@@ -9,10 +9,8 @@ config CLK_BCM_KONA
9 in the BCM281xx and BCM21664 families. 9 in the BCM281xx and BCM21664 families.
10 10
11config COMMON_CLK_IPROC 11config COMMON_CLK_IPROC
12 bool "Broadcom iProc clock support" 12 bool
13 depends on ARCH_BCM_IPROC || COMPILE_TEST
14 depends on COMMON_CLK 13 depends on COMMON_CLK
15 default ARCH_BCM_IPROC
16 help 14 help
17 Enable common clock framework support for Broadcom SoCs 15 Enable common clock framework support for Broadcom SoCs
18 based on the iProc architecture 16 based on the iProc architecture
diff --git a/drivers/clk/bcm/Makefile b/drivers/clk/bcm/Makefile
index ee2349bbe1f1..3fc95060d875 100644
--- a/drivers/clk/bcm/Makefile
+++ b/drivers/clk/bcm/Makefile
@@ -4,4 +4,7 @@ obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm281xx.o
4obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm21664.o 4obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm21664.o
5obj-$(CONFIG_COMMON_CLK_IPROC) += clk-iproc-armpll.o clk-iproc-pll.o clk-iproc-asiu.o 5obj-$(CONFIG_COMMON_CLK_IPROC) += clk-iproc-armpll.o clk-iproc-pll.o clk-iproc-asiu.o
6obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o 6obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o
7obj-$(CONFIG_COMMON_CLK_IPROC) += clk-ns2.o
7obj-$(CONFIG_ARCH_BCM_CYGNUS) += clk-cygnus.o 8obj-$(CONFIG_ARCH_BCM_CYGNUS) += clk-cygnus.o
9obj-$(CONFIG_ARCH_BCM_NSP) += clk-nsp.o
10obj-$(CONFIG_ARCH_BCM_5301X) += clk-nsp.o
diff --git a/drivers/clk/bcm/clk-cygnus.c b/drivers/clk/bcm/clk-cygnus.c
index 316c60337661..3a228b6d4fee 100644
--- a/drivers/clk/bcm/clk-cygnus.c
+++ b/drivers/clk/bcm/clk-cygnus.c
@@ -23,28 +23,30 @@
23#include <dt-bindings/clock/bcm-cygnus.h> 23#include <dt-bindings/clock/bcm-cygnus.h>
24#include "clk-iproc.h" 24#include "clk-iproc.h"
25 25
26#define reg_val(o, s, w) { .offset = o, .shift = s, .width = w, } 26#define REG_VAL(o, s, w) { .offset = o, .shift = s, .width = w, }
27 27
28#define aon_val(o, pw, ps, is) { .offset = o, .pwr_width = pw, \ 28#define AON_VAL(o, pw, ps, is) { .offset = o, .pwr_width = pw, \
29 .pwr_shift = ps, .iso_shift = is } 29 .pwr_shift = ps, .iso_shift = is }
30 30
31#define sw_ctrl_val(o, s) { .offset = o, .shift = s, } 31#define SW_CTRL_VAL(o, s) { .offset = o, .shift = s, }
32 32
33#define asiu_div_val(o, es, hs, hw, ls, lw) \ 33#define ASIU_DIV_VAL(o, es, hs, hw, ls, lw) \
34 { .offset = o, .en_shift = es, .high_shift = hs, \ 34 { .offset = o, .en_shift = es, .high_shift = hs, \
35 .high_width = hw, .low_shift = ls, .low_width = lw } 35 .high_width = hw, .low_shift = ls, .low_width = lw }
36 36
37#define reset_val(o, rs, prs, kis, kiw, kps, kpw, kas, kaw) { .offset = o, \ 37#define RESET_VAL(o, rs, prs) { .offset = o, .reset_shift = rs, \
38 .reset_shift = rs, .p_reset_shift = prs, .ki_shift = kis, \ 38 .p_reset_shift = prs }
39 .ki_width = kiw, .kp_shift = kps, .kp_width = kpw, .ka_shift = kas, \ 39
40#define DF_VAL(o, kis, kiw, kps, kpw, kas, kaw) { .offset = o, .ki_shift = kis,\
41 .ki_width = kiw, .kp_shift = kps, .kp_width = kpw, .ka_shift = kas, \
40 .ka_width = kaw } 42 .ka_width = kaw }
41 43
42#define vco_ctrl_val(uo, lo) { .u_offset = uo, .l_offset = lo } 44#define VCO_CTRL_VAL(uo, lo) { .u_offset = uo, .l_offset = lo }
43 45
44#define enable_val(o, es, hs, bs) { .offset = o, .enable_shift = es, \ 46#define ENABLE_VAL(o, es, hs, bs) { .offset = o, .enable_shift = es, \
45 .hold_shift = hs, .bypass_shift = bs } 47 .hold_shift = hs, .bypass_shift = bs }
46 48
47#define asiu_gate_val(o, es) { .offset = o, .en_shift = es } 49#define ASIU_GATE_VAL(o, es) { .offset = o, .en_shift = es }
48 50
49static void __init cygnus_armpll_init(struct device_node *node) 51static void __init cygnus_armpll_init(struct device_node *node)
50{ 52{
@@ -55,52 +57,53 @@ CLK_OF_DECLARE(cygnus_armpll, "brcm,cygnus-armpll", cygnus_armpll_init);
55static const struct iproc_pll_ctrl genpll = { 57static const struct iproc_pll_ctrl genpll = {
56 .flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC | 58 .flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC |
57 IPROC_CLK_PLL_NEEDS_SW_CFG, 59 IPROC_CLK_PLL_NEEDS_SW_CFG,
58 .aon = aon_val(0x0, 2, 1, 0), 60 .aon = AON_VAL(0x0, 2, 1, 0),
59 .reset = reset_val(0x0, 11, 10, 4, 3, 0, 4, 7, 3), 61 .reset = RESET_VAL(0x0, 11, 10),
60 .sw_ctrl = sw_ctrl_val(0x10, 31), 62 .dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 3),
61 .ndiv_int = reg_val(0x10, 20, 10), 63 .sw_ctrl = SW_CTRL_VAL(0x10, 31),
62 .ndiv_frac = reg_val(0x10, 0, 20), 64 .ndiv_int = REG_VAL(0x10, 20, 10),
63 .pdiv = reg_val(0x14, 0, 4), 65 .ndiv_frac = REG_VAL(0x10, 0, 20),
64 .vco_ctrl = vco_ctrl_val(0x18, 0x1c), 66 .pdiv = REG_VAL(0x14, 0, 4),
65 .status = reg_val(0x28, 12, 1), 67 .vco_ctrl = VCO_CTRL_VAL(0x18, 0x1c),
68 .status = REG_VAL(0x28, 12, 1),
66}; 69};
67 70
68static const struct iproc_clk_ctrl genpll_clk[] = { 71static const struct iproc_clk_ctrl genpll_clk[] = {
69 [BCM_CYGNUS_GENPLL_AXI21_CLK] = { 72 [BCM_CYGNUS_GENPLL_AXI21_CLK] = {
70 .channel = BCM_CYGNUS_GENPLL_AXI21_CLK, 73 .channel = BCM_CYGNUS_GENPLL_AXI21_CLK,
71 .flags = IPROC_CLK_AON, 74 .flags = IPROC_CLK_AON,
72 .enable = enable_val(0x4, 6, 0, 12), 75 .enable = ENABLE_VAL(0x4, 6, 0, 12),
73 .mdiv = reg_val(0x20, 0, 8), 76 .mdiv = REG_VAL(0x20, 0, 8),
74 }, 77 },
75 [BCM_CYGNUS_GENPLL_250MHZ_CLK] = { 78 [BCM_CYGNUS_GENPLL_250MHZ_CLK] = {
76 .channel = BCM_CYGNUS_GENPLL_250MHZ_CLK, 79 .channel = BCM_CYGNUS_GENPLL_250MHZ_CLK,
77 .flags = IPROC_CLK_AON, 80 .flags = IPROC_CLK_AON,
78 .enable = enable_val(0x4, 7, 1, 13), 81 .enable = ENABLE_VAL(0x4, 7, 1, 13),
79 .mdiv = reg_val(0x20, 10, 8), 82 .mdiv = REG_VAL(0x20, 10, 8),
80 }, 83 },
81 [BCM_CYGNUS_GENPLL_IHOST_SYS_CLK] = { 84 [BCM_CYGNUS_GENPLL_IHOST_SYS_CLK] = {
82 .channel = BCM_CYGNUS_GENPLL_IHOST_SYS_CLK, 85 .channel = BCM_CYGNUS_GENPLL_IHOST_SYS_CLK,
83 .flags = IPROC_CLK_AON, 86 .flags = IPROC_CLK_AON,
84 .enable = enable_val(0x4, 8, 2, 14), 87 .enable = ENABLE_VAL(0x4, 8, 2, 14),
85 .mdiv = reg_val(0x20, 20, 8), 88 .mdiv = REG_VAL(0x20, 20, 8),
86 }, 89 },
87 [BCM_CYGNUS_GENPLL_ENET_SW_CLK] = { 90 [BCM_CYGNUS_GENPLL_ENET_SW_CLK] = {
88 .channel = BCM_CYGNUS_GENPLL_ENET_SW_CLK, 91 .channel = BCM_CYGNUS_GENPLL_ENET_SW_CLK,
89 .flags = IPROC_CLK_AON, 92 .flags = IPROC_CLK_AON,
90 .enable = enable_val(0x4, 9, 3, 15), 93 .enable = ENABLE_VAL(0x4, 9, 3, 15),
91 .mdiv = reg_val(0x24, 0, 8), 94 .mdiv = REG_VAL(0x24, 0, 8),
92 }, 95 },
93 [BCM_CYGNUS_GENPLL_AUDIO_125_CLK] = { 96 [BCM_CYGNUS_GENPLL_AUDIO_125_CLK] = {
94 .channel = BCM_CYGNUS_GENPLL_AUDIO_125_CLK, 97 .channel = BCM_CYGNUS_GENPLL_AUDIO_125_CLK,
95 .flags = IPROC_CLK_AON, 98 .flags = IPROC_CLK_AON,
96 .enable = enable_val(0x4, 10, 4, 16), 99 .enable = ENABLE_VAL(0x4, 10, 4, 16),
97 .mdiv = reg_val(0x24, 10, 8), 100 .mdiv = REG_VAL(0x24, 10, 8),
98 }, 101 },
99 [BCM_CYGNUS_GENPLL_CAN_CLK] = { 102 [BCM_CYGNUS_GENPLL_CAN_CLK] = {
100 .channel = BCM_CYGNUS_GENPLL_CAN_CLK, 103 .channel = BCM_CYGNUS_GENPLL_CAN_CLK,
101 .flags = IPROC_CLK_AON, 104 .flags = IPROC_CLK_AON,
102 .enable = enable_val(0x4, 11, 5, 17), 105 .enable = ENABLE_VAL(0x4, 11, 5, 17),
103 .mdiv = reg_val(0x24, 20, 8), 106 .mdiv = REG_VAL(0x24, 20, 8),
104 }, 107 },
105}; 108};
106 109
@@ -113,51 +116,52 @@ CLK_OF_DECLARE(cygnus_genpll, "brcm,cygnus-genpll", cygnus_genpll_clk_init);
113 116
114static const struct iproc_pll_ctrl lcpll0 = { 117static const struct iproc_pll_ctrl lcpll0 = {
115 .flags = IPROC_CLK_AON | IPROC_CLK_PLL_NEEDS_SW_CFG, 118 .flags = IPROC_CLK_AON | IPROC_CLK_PLL_NEEDS_SW_CFG,
116 .aon = aon_val(0x0, 2, 5, 4), 119 .aon = AON_VAL(0x0, 2, 5, 4),
117 .reset = reset_val(0x0, 31, 30, 27, 3, 23, 4, 19, 4), 120 .reset = RESET_VAL(0x0, 31, 30),
118 .sw_ctrl = sw_ctrl_val(0x4, 31), 121 .dig_filter = DF_VAL(0x0, 27, 3, 23, 4, 19, 4),
119 .ndiv_int = reg_val(0x4, 16, 10), 122 .sw_ctrl = SW_CTRL_VAL(0x4, 31),
120 .pdiv = reg_val(0x4, 26, 4), 123 .ndiv_int = REG_VAL(0x4, 16, 10),
121 .vco_ctrl = vco_ctrl_val(0x10, 0x14), 124 .pdiv = REG_VAL(0x4, 26, 4),
122 .status = reg_val(0x18, 12, 1), 125 .vco_ctrl = VCO_CTRL_VAL(0x10, 0x14),
126 .status = REG_VAL(0x18, 12, 1),
123}; 127};
124 128
125static const struct iproc_clk_ctrl lcpll0_clk[] = { 129static const struct iproc_clk_ctrl lcpll0_clk[] = {
126 [BCM_CYGNUS_LCPLL0_PCIE_PHY_REF_CLK] = { 130 [BCM_CYGNUS_LCPLL0_PCIE_PHY_REF_CLK] = {
127 .channel = BCM_CYGNUS_LCPLL0_PCIE_PHY_REF_CLK, 131 .channel = BCM_CYGNUS_LCPLL0_PCIE_PHY_REF_CLK,
128 .flags = IPROC_CLK_AON, 132 .flags = IPROC_CLK_AON,
129 .enable = enable_val(0x0, 7, 1, 13), 133 .enable = ENABLE_VAL(0x0, 7, 1, 13),
130 .mdiv = reg_val(0x8, 0, 8), 134 .mdiv = REG_VAL(0x8, 0, 8),
131 }, 135 },
132 [BCM_CYGNUS_LCPLL0_DDR_PHY_CLK] = { 136 [BCM_CYGNUS_LCPLL0_DDR_PHY_CLK] = {
133 .channel = BCM_CYGNUS_LCPLL0_DDR_PHY_CLK, 137 .channel = BCM_CYGNUS_LCPLL0_DDR_PHY_CLK,
134 .flags = IPROC_CLK_AON, 138 .flags = IPROC_CLK_AON,
135 .enable = enable_val(0x0, 8, 2, 14), 139 .enable = ENABLE_VAL(0x0, 8, 2, 14),
136 .mdiv = reg_val(0x8, 10, 8), 140 .mdiv = REG_VAL(0x8, 10, 8),
137 }, 141 },
138 [BCM_CYGNUS_LCPLL0_SDIO_CLK] = { 142 [BCM_CYGNUS_LCPLL0_SDIO_CLK] = {
139 .channel = BCM_CYGNUS_LCPLL0_SDIO_CLK, 143 .channel = BCM_CYGNUS_LCPLL0_SDIO_CLK,
140 .flags = IPROC_CLK_AON, 144 .flags = IPROC_CLK_AON,
141 .enable = enable_val(0x0, 9, 3, 15), 145 .enable = ENABLE_VAL(0x0, 9, 3, 15),
142 .mdiv = reg_val(0x8, 20, 8), 146 .mdiv = REG_VAL(0x8, 20, 8),
143 }, 147 },
144 [BCM_CYGNUS_LCPLL0_USB_PHY_REF_CLK] = { 148 [BCM_CYGNUS_LCPLL0_USB_PHY_REF_CLK] = {
145 .channel = BCM_CYGNUS_LCPLL0_USB_PHY_REF_CLK, 149 .channel = BCM_CYGNUS_LCPLL0_USB_PHY_REF_CLK,
146 .flags = IPROC_CLK_AON, 150 .flags = IPROC_CLK_AON,
147 .enable = enable_val(0x0, 10, 4, 16), 151 .enable = ENABLE_VAL(0x0, 10, 4, 16),
148 .mdiv = reg_val(0xc, 0, 8), 152 .mdiv = REG_VAL(0xc, 0, 8),
149 }, 153 },
150 [BCM_CYGNUS_LCPLL0_SMART_CARD_CLK] = { 154 [BCM_CYGNUS_LCPLL0_SMART_CARD_CLK] = {
151 .channel = BCM_CYGNUS_LCPLL0_SMART_CARD_CLK, 155 .channel = BCM_CYGNUS_LCPLL0_SMART_CARD_CLK,
152 .flags = IPROC_CLK_AON, 156 .flags = IPROC_CLK_AON,
153 .enable = enable_val(0x0, 11, 5, 17), 157 .enable = ENABLE_VAL(0x0, 11, 5, 17),
154 .mdiv = reg_val(0xc, 10, 8), 158 .mdiv = REG_VAL(0xc, 10, 8),
155 }, 159 },
156 [BCM_CYGNUS_LCPLL0_CH5_UNUSED] = { 160 [BCM_CYGNUS_LCPLL0_CH5_UNUSED] = {
157 .channel = BCM_CYGNUS_LCPLL0_CH5_UNUSED, 161 .channel = BCM_CYGNUS_LCPLL0_CH5_UNUSED,
158 .flags = IPROC_CLK_AON, 162 .flags = IPROC_CLK_AON,
159 .enable = enable_val(0x0, 12, 6, 18), 163 .enable = ENABLE_VAL(0x0, 12, 6, 18),
160 .mdiv = reg_val(0xc, 20, 8), 164 .mdiv = REG_VAL(0xc, 20, 8),
161 }, 165 },
162}; 166};
163 167
@@ -189,52 +193,53 @@ static const struct iproc_pll_vco_param mipipll_vco_params[] = {
189static const struct iproc_pll_ctrl mipipll = { 193static const struct iproc_pll_ctrl mipipll = {
190 .flags = IPROC_CLK_PLL_ASIU | IPROC_CLK_PLL_HAS_NDIV_FRAC | 194 .flags = IPROC_CLK_PLL_ASIU | IPROC_CLK_PLL_HAS_NDIV_FRAC |
191 IPROC_CLK_NEEDS_READ_BACK, 195 IPROC_CLK_NEEDS_READ_BACK,
192 .aon = aon_val(0x0, 4, 17, 16), 196 .aon = AON_VAL(0x0, 4, 17, 16),
193 .asiu = asiu_gate_val(0x0, 3), 197 .asiu = ASIU_GATE_VAL(0x0, 3),
194 .reset = reset_val(0x0, 11, 10, 4, 3, 0, 4, 7, 4), 198 .reset = RESET_VAL(0x0, 11, 10),
195 .ndiv_int = reg_val(0x10, 20, 10), 199 .dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 4),
196 .ndiv_frac = reg_val(0x10, 0, 20), 200 .ndiv_int = REG_VAL(0x10, 20, 10),
197 .pdiv = reg_val(0x14, 0, 4), 201 .ndiv_frac = REG_VAL(0x10, 0, 20),
198 .vco_ctrl = vco_ctrl_val(0x18, 0x1c), 202 .pdiv = REG_VAL(0x14, 0, 4),
199 .status = reg_val(0x28, 12, 1), 203 .vco_ctrl = VCO_CTRL_VAL(0x18, 0x1c),
204 .status = REG_VAL(0x28, 12, 1),
200}; 205};
201 206
202static const struct iproc_clk_ctrl mipipll_clk[] = { 207static const struct iproc_clk_ctrl mipipll_clk[] = {
203 [BCM_CYGNUS_MIPIPLL_CH0_UNUSED] = { 208 [BCM_CYGNUS_MIPIPLL_CH0_UNUSED] = {
204 .channel = BCM_CYGNUS_MIPIPLL_CH0_UNUSED, 209 .channel = BCM_CYGNUS_MIPIPLL_CH0_UNUSED,
205 .flags = IPROC_CLK_NEEDS_READ_BACK, 210 .flags = IPROC_CLK_NEEDS_READ_BACK,
206 .enable = enable_val(0x4, 12, 6, 18), 211 .enable = ENABLE_VAL(0x4, 12, 6, 18),
207 .mdiv = reg_val(0x20, 0, 8), 212 .mdiv = REG_VAL(0x20, 0, 8),
208 }, 213 },
209 [BCM_CYGNUS_MIPIPLL_CH1_LCD] = { 214 [BCM_CYGNUS_MIPIPLL_CH1_LCD] = {
210 .channel = BCM_CYGNUS_MIPIPLL_CH1_LCD, 215 .channel = BCM_CYGNUS_MIPIPLL_CH1_LCD,
211 .flags = IPROC_CLK_NEEDS_READ_BACK, 216 .flags = IPROC_CLK_NEEDS_READ_BACK,
212 .enable = enable_val(0x4, 13, 7, 19), 217 .enable = ENABLE_VAL(0x4, 13, 7, 19),
213 .mdiv = reg_val(0x20, 10, 8), 218 .mdiv = REG_VAL(0x20, 10, 8),
214 }, 219 },
215 [BCM_CYGNUS_MIPIPLL_CH2_V3D] = { 220 [BCM_CYGNUS_MIPIPLL_CH2_V3D] = {
216 .channel = BCM_CYGNUS_MIPIPLL_CH2_V3D, 221 .channel = BCM_CYGNUS_MIPIPLL_CH2_V3D,
217 .flags = IPROC_CLK_NEEDS_READ_BACK, 222 .flags = IPROC_CLK_NEEDS_READ_BACK,
218 .enable = enable_val(0x4, 14, 8, 20), 223 .enable = ENABLE_VAL(0x4, 14, 8, 20),
219 .mdiv = reg_val(0x20, 20, 8), 224 .mdiv = REG_VAL(0x20, 20, 8),
220 }, 225 },
221 [BCM_CYGNUS_MIPIPLL_CH3_UNUSED] = { 226 [BCM_CYGNUS_MIPIPLL_CH3_UNUSED] = {
222 .channel = BCM_CYGNUS_MIPIPLL_CH3_UNUSED, 227 .channel = BCM_CYGNUS_MIPIPLL_CH3_UNUSED,
223 .flags = IPROC_CLK_NEEDS_READ_BACK, 228 .flags = IPROC_CLK_NEEDS_READ_BACK,
224 .enable = enable_val(0x4, 15, 9, 21), 229 .enable = ENABLE_VAL(0x4, 15, 9, 21),
225 .mdiv = reg_val(0x24, 0, 8), 230 .mdiv = REG_VAL(0x24, 0, 8),
226 }, 231 },
227 [BCM_CYGNUS_MIPIPLL_CH4_UNUSED] = { 232 [BCM_CYGNUS_MIPIPLL_CH4_UNUSED] = {
228 .channel = BCM_CYGNUS_MIPIPLL_CH4_UNUSED, 233 .channel = BCM_CYGNUS_MIPIPLL_CH4_UNUSED,
229 .flags = IPROC_CLK_NEEDS_READ_BACK, 234 .flags = IPROC_CLK_NEEDS_READ_BACK,
230 .enable = enable_val(0x4, 16, 10, 22), 235 .enable = ENABLE_VAL(0x4, 16, 10, 22),
231 .mdiv = reg_val(0x24, 10, 8), 236 .mdiv = REG_VAL(0x24, 10, 8),
232 }, 237 },
233 [BCM_CYGNUS_MIPIPLL_CH5_UNUSED] = { 238 [BCM_CYGNUS_MIPIPLL_CH5_UNUSED] = {
234 .channel = BCM_CYGNUS_MIPIPLL_CH5_UNUSED, 239 .channel = BCM_CYGNUS_MIPIPLL_CH5_UNUSED,
235 .flags = IPROC_CLK_NEEDS_READ_BACK, 240 .flags = IPROC_CLK_NEEDS_READ_BACK,
236 .enable = enable_val(0x4, 17, 11, 23), 241 .enable = ENABLE_VAL(0x4, 17, 11, 23),
237 .mdiv = reg_val(0x24, 20, 8), 242 .mdiv = REG_VAL(0x24, 20, 8),
238 }, 243 },
239}; 244};
240 245
@@ -247,15 +252,15 @@ static void __init cygnus_mipipll_clk_init(struct device_node *node)
247CLK_OF_DECLARE(cygnus_mipipll, "brcm,cygnus-mipipll", cygnus_mipipll_clk_init); 252CLK_OF_DECLARE(cygnus_mipipll, "brcm,cygnus-mipipll", cygnus_mipipll_clk_init);
248 253
249static const struct iproc_asiu_div asiu_div[] = { 254static const struct iproc_asiu_div asiu_div[] = {
250 [BCM_CYGNUS_ASIU_KEYPAD_CLK] = asiu_div_val(0x0, 31, 16, 10, 0, 10), 255 [BCM_CYGNUS_ASIU_KEYPAD_CLK] = ASIU_DIV_VAL(0x0, 31, 16, 10, 0, 10),
251 [BCM_CYGNUS_ASIU_ADC_CLK] = asiu_div_val(0x4, 31, 16, 10, 0, 10), 256 [BCM_CYGNUS_ASIU_ADC_CLK] = ASIU_DIV_VAL(0x4, 31, 16, 10, 0, 10),
252 [BCM_CYGNUS_ASIU_PWM_CLK] = asiu_div_val(0x8, 31, 16, 10, 0, 10), 257 [BCM_CYGNUS_ASIU_PWM_CLK] = ASIU_DIV_VAL(0x8, 31, 16, 10, 0, 10),
253}; 258};
254 259
255static const struct iproc_asiu_gate asiu_gate[] = { 260static const struct iproc_asiu_gate asiu_gate[] = {
256 [BCM_CYGNUS_ASIU_KEYPAD_CLK] = asiu_gate_val(0x0, 7), 261 [BCM_CYGNUS_ASIU_KEYPAD_CLK] = ASIU_GATE_VAL(0x0, 7),
257 [BCM_CYGNUS_ASIU_ADC_CLK] = asiu_gate_val(0x0, 9), 262 [BCM_CYGNUS_ASIU_ADC_CLK] = ASIU_GATE_VAL(0x0, 9),
258 [BCM_CYGNUS_ASIU_PWM_CLK] = asiu_gate_val(IPROC_CLK_INVALID_OFFSET, 0), 263 [BCM_CYGNUS_ASIU_PWM_CLK] = ASIU_GATE_VAL(IPROC_CLK_INVALID_OFFSET, 0),
259}; 264};
260 265
261static void __init cygnus_asiu_init(struct device_node *node) 266static void __init cygnus_asiu_init(struct device_node *node)
diff --git a/drivers/clk/bcm/clk-iproc-pll.c b/drivers/clk/bcm/clk-iproc-pll.c
index d679ab869653..afd5891ac9e6 100644
--- a/drivers/clk/bcm/clk-iproc-pll.c
+++ b/drivers/clk/bcm/clk-iproc-pll.c
@@ -74,7 +74,8 @@ struct iproc_clk {
74}; 74};
75 75
76struct iproc_pll { 76struct iproc_pll {
77 void __iomem *pll_base; 77 void __iomem *status_base;
78 void __iomem *control_base;
78 void __iomem *pwr_base; 79 void __iomem *pwr_base;
79 void __iomem *asiu_base; 80 void __iomem *asiu_base;
80 81
@@ -127,7 +128,7 @@ static int pll_wait_for_lock(struct iproc_pll *pll)
127 const struct iproc_pll_ctrl *ctrl = pll->ctrl; 128 const struct iproc_pll_ctrl *ctrl = pll->ctrl;
128 129
129 for (i = 0; i < LOCK_DELAY; i++) { 130 for (i = 0; i < LOCK_DELAY; i++) {
130 u32 val = readl(pll->pll_base + ctrl->status.offset); 131 u32 val = readl(pll->status_base + ctrl->status.offset);
131 132
132 if (val & (1 << ctrl->status.shift)) 133 if (val & (1 << ctrl->status.shift))
133 return 0; 134 return 0;
@@ -137,6 +138,18 @@ static int pll_wait_for_lock(struct iproc_pll *pll)
137 return -EIO; 138 return -EIO;
138} 139}
139 140
141static void iproc_pll_write(const struct iproc_pll *pll, void __iomem *base,
142 const u32 offset, u32 val)
143{
144 const struct iproc_pll_ctrl *ctrl = pll->ctrl;
145
146 writel(val, base + offset);
147
148 if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK &&
149 (base == pll->status_base || base == pll->control_base)))
150 val = readl(base + offset);
151}
152
140static void __pll_disable(struct iproc_pll *pll) 153static void __pll_disable(struct iproc_pll *pll)
141{ 154{
142 const struct iproc_pll_ctrl *ctrl = pll->ctrl; 155 const struct iproc_pll_ctrl *ctrl = pll->ctrl;
@@ -145,17 +158,25 @@ static void __pll_disable(struct iproc_pll *pll)
145 if (ctrl->flags & IPROC_CLK_PLL_ASIU) { 158 if (ctrl->flags & IPROC_CLK_PLL_ASIU) {
146 val = readl(pll->asiu_base + ctrl->asiu.offset); 159 val = readl(pll->asiu_base + ctrl->asiu.offset);
147 val &= ~(1 << ctrl->asiu.en_shift); 160 val &= ~(1 << ctrl->asiu.en_shift);
148 writel(val, pll->asiu_base + ctrl->asiu.offset); 161 iproc_pll_write(pll, pll->asiu_base, ctrl->asiu.offset, val);
162 }
163
164 if (ctrl->flags & IPROC_CLK_EMBED_PWRCTRL) {
165 val = readl(pll->control_base + ctrl->aon.offset);
166 val |= bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift;
167 iproc_pll_write(pll, pll->control_base, ctrl->aon.offset, val);
149 } 168 }
150 169
151 /* latch input value so core power can be shut down */ 170 if (pll->pwr_base) {
152 val = readl(pll->pwr_base + ctrl->aon.offset); 171 /* latch input value so core power can be shut down */
153 val |= (1 << ctrl->aon.iso_shift); 172 val = readl(pll->pwr_base + ctrl->aon.offset);
154 writel(val, pll->pwr_base + ctrl->aon.offset); 173 val |= 1 << ctrl->aon.iso_shift;
174 iproc_pll_write(pll, pll->pwr_base, ctrl->aon.offset, val);
155 175
156 /* power down the core */ 176 /* power down the core */
157 val &= ~(bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift); 177 val &= ~(bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift);
158 writel(val, pll->pwr_base + ctrl->aon.offset); 178 iproc_pll_write(pll, pll->pwr_base, ctrl->aon.offset, val);
179 }
159} 180}
160 181
161static int __pll_enable(struct iproc_pll *pll) 182static int __pll_enable(struct iproc_pll *pll)
@@ -163,17 +184,25 @@ static int __pll_enable(struct iproc_pll *pll)
163 const struct iproc_pll_ctrl *ctrl = pll->ctrl; 184 const struct iproc_pll_ctrl *ctrl = pll->ctrl;
164 u32 val; 185 u32 val;
165 186
166 /* power up the PLL and make sure it's not latched */ 187 if (ctrl->flags & IPROC_CLK_EMBED_PWRCTRL) {
167 val = readl(pll->pwr_base + ctrl->aon.offset); 188 val = readl(pll->control_base + ctrl->aon.offset);
168 val |= bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift; 189 val &= ~(bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift);
169 val &= ~(1 << ctrl->aon.iso_shift); 190 iproc_pll_write(pll, pll->control_base, ctrl->aon.offset, val);
170 writel(val, pll->pwr_base + ctrl->aon.offset); 191 }
192
193 if (pll->pwr_base) {
194 /* power up the PLL and make sure it's not latched */
195 val = readl(pll->pwr_base + ctrl->aon.offset);
196 val |= bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift;
197 val &= ~(1 << ctrl->aon.iso_shift);
198 iproc_pll_write(pll, pll->pwr_base, ctrl->aon.offset, val);
199 }
171 200
172 /* certain PLLs also need to be ungated from the ASIU top level */ 201 /* certain PLLs also need to be ungated from the ASIU top level */
173 if (ctrl->flags & IPROC_CLK_PLL_ASIU) { 202 if (ctrl->flags & IPROC_CLK_PLL_ASIU) {
174 val = readl(pll->asiu_base + ctrl->asiu.offset); 203 val = readl(pll->asiu_base + ctrl->asiu.offset);
175 val |= (1 << ctrl->asiu.en_shift); 204 val |= (1 << ctrl->asiu.en_shift);
176 writel(val, pll->asiu_base + ctrl->asiu.offset); 205 iproc_pll_write(pll, pll->asiu_base, ctrl->asiu.offset, val);
177 } 206 }
178 207
179 return 0; 208 return 0;
@@ -185,11 +214,9 @@ static void __pll_put_in_reset(struct iproc_pll *pll)
185 const struct iproc_pll_ctrl *ctrl = pll->ctrl; 214 const struct iproc_pll_ctrl *ctrl = pll->ctrl;
186 const struct iproc_pll_reset_ctrl *reset = &ctrl->reset; 215 const struct iproc_pll_reset_ctrl *reset = &ctrl->reset;
187 216
188 val = readl(pll->pll_base + reset->offset); 217 val = readl(pll->control_base + reset->offset);
189 val &= ~(1 << reset->reset_shift | 1 << reset->p_reset_shift); 218 val &= ~(1 << reset->reset_shift | 1 << reset->p_reset_shift);
190 writel(val, pll->pll_base + reset->offset); 219 iproc_pll_write(pll, pll->control_base, reset->offset, val);
191 if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
192 readl(pll->pll_base + reset->offset);
193} 220}
194 221
195static void __pll_bring_out_reset(struct iproc_pll *pll, unsigned int kp, 222static void __pll_bring_out_reset(struct iproc_pll *pll, unsigned int kp,
@@ -198,17 +225,19 @@ static void __pll_bring_out_reset(struct iproc_pll *pll, unsigned int kp,
198 u32 val; 225 u32 val;
199 const struct iproc_pll_ctrl *ctrl = pll->ctrl; 226 const struct iproc_pll_ctrl *ctrl = pll->ctrl;
200 const struct iproc_pll_reset_ctrl *reset = &ctrl->reset; 227 const struct iproc_pll_reset_ctrl *reset = &ctrl->reset;
228 const struct iproc_pll_dig_filter_ctrl *dig_filter = &ctrl->dig_filter;
201 229
202 val = readl(pll->pll_base + reset->offset); 230 val = readl(pll->control_base + dig_filter->offset);
203 val &= ~(bit_mask(reset->ki_width) << reset->ki_shift | 231 val &= ~(bit_mask(dig_filter->ki_width) << dig_filter->ki_shift |
204 bit_mask(reset->kp_width) << reset->kp_shift | 232 bit_mask(dig_filter->kp_width) << dig_filter->kp_shift |
205 bit_mask(reset->ka_width) << reset->ka_shift); 233 bit_mask(dig_filter->ka_width) << dig_filter->ka_shift);
206 val |= ki << reset->ki_shift | kp << reset->kp_shift | 234 val |= ki << dig_filter->ki_shift | kp << dig_filter->kp_shift |
207 ka << reset->ka_shift; 235 ka << dig_filter->ka_shift;
236 iproc_pll_write(pll, pll->control_base, dig_filter->offset, val);
237
238 val = readl(pll->control_base + reset->offset);
208 val |= 1 << reset->reset_shift | 1 << reset->p_reset_shift; 239 val |= 1 << reset->reset_shift | 1 << reset->p_reset_shift;
209 writel(val, pll->pll_base + reset->offset); 240 iproc_pll_write(pll, pll->control_base, reset->offset, val);
210 if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
211 readl(pll->pll_base + reset->offset);
212} 241}
213 242
214static int pll_set_rate(struct iproc_clk *clk, unsigned int rate_index, 243static int pll_set_rate(struct iproc_clk *clk, unsigned int rate_index,
@@ -263,10 +292,9 @@ static int pll_set_rate(struct iproc_clk *clk, unsigned int rate_index,
263 /* put PLL in reset */ 292 /* put PLL in reset */
264 __pll_put_in_reset(pll); 293 __pll_put_in_reset(pll);
265 294
266 writel(0, pll->pll_base + ctrl->vco_ctrl.u_offset); 295 iproc_pll_write(pll, pll->control_base, ctrl->vco_ctrl.u_offset, 0);
267 if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK)) 296
268 readl(pll->pll_base + ctrl->vco_ctrl.u_offset); 297 val = readl(pll->control_base + ctrl->vco_ctrl.l_offset);
269 val = readl(pll->pll_base + ctrl->vco_ctrl.l_offset);
270 298
271 if (rate >= VCO_LOW && rate < VCO_MID) 299 if (rate >= VCO_LOW && rate < VCO_MID)
272 val |= (1 << PLL_VCO_LOW_SHIFT); 300 val |= (1 << PLL_VCO_LOW_SHIFT);
@@ -276,36 +304,29 @@ static int pll_set_rate(struct iproc_clk *clk, unsigned int rate_index,
276 else 304 else
277 val |= (1 << PLL_VCO_HIGH_SHIFT); 305 val |= (1 << PLL_VCO_HIGH_SHIFT);
278 306
279 writel(val, pll->pll_base + ctrl->vco_ctrl.l_offset); 307 iproc_pll_write(pll, pll->control_base, ctrl->vco_ctrl.l_offset, val);
280 if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
281 readl(pll->pll_base + ctrl->vco_ctrl.l_offset);
282 308
283 /* program integer part of NDIV */ 309 /* program integer part of NDIV */
284 val = readl(pll->pll_base + ctrl->ndiv_int.offset); 310 val = readl(pll->control_base + ctrl->ndiv_int.offset);
285 val &= ~(bit_mask(ctrl->ndiv_int.width) << ctrl->ndiv_int.shift); 311 val &= ~(bit_mask(ctrl->ndiv_int.width) << ctrl->ndiv_int.shift);
286 val |= vco->ndiv_int << ctrl->ndiv_int.shift; 312 val |= vco->ndiv_int << ctrl->ndiv_int.shift;
287 writel(val, pll->pll_base + ctrl->ndiv_int.offset); 313 iproc_pll_write(pll, pll->control_base, ctrl->ndiv_int.offset, val);
288 if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
289 readl(pll->pll_base + ctrl->ndiv_int.offset);
290 314
291 /* program fractional part of NDIV */ 315 /* program fractional part of NDIV */
292 if (ctrl->flags & IPROC_CLK_PLL_HAS_NDIV_FRAC) { 316 if (ctrl->flags & IPROC_CLK_PLL_HAS_NDIV_FRAC) {
293 val = readl(pll->pll_base + ctrl->ndiv_frac.offset); 317 val = readl(pll->control_base + ctrl->ndiv_frac.offset);
294 val &= ~(bit_mask(ctrl->ndiv_frac.width) << 318 val &= ~(bit_mask(ctrl->ndiv_frac.width) <<
295 ctrl->ndiv_frac.shift); 319 ctrl->ndiv_frac.shift);
296 val |= vco->ndiv_frac << ctrl->ndiv_frac.shift; 320 val |= vco->ndiv_frac << ctrl->ndiv_frac.shift;
297 writel(val, pll->pll_base + ctrl->ndiv_frac.offset); 321 iproc_pll_write(pll, pll->control_base, ctrl->ndiv_frac.offset,
298 if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK)) 322 val);
299 readl(pll->pll_base + ctrl->ndiv_frac.offset);
300 } 323 }
301 324
302 /* program PDIV */ 325 /* program PDIV */
303 val = readl(pll->pll_base + ctrl->pdiv.offset); 326 val = readl(pll->control_base + ctrl->pdiv.offset);
304 val &= ~(bit_mask(ctrl->pdiv.width) << ctrl->pdiv.shift); 327 val &= ~(bit_mask(ctrl->pdiv.width) << ctrl->pdiv.shift);
305 val |= vco->pdiv << ctrl->pdiv.shift; 328 val |= vco->pdiv << ctrl->pdiv.shift;
306 writel(val, pll->pll_base + ctrl->pdiv.offset); 329 iproc_pll_write(pll, pll->control_base, ctrl->pdiv.offset, val);
307 if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
308 readl(pll->pll_base + ctrl->pdiv.offset);
309 330
310 __pll_bring_out_reset(pll, kp, ka, ki); 331 __pll_bring_out_reset(pll, kp, ka, ki);
311 332
@@ -352,7 +373,7 @@ static unsigned long iproc_pll_recalc_rate(struct clk_hw *hw,
352 return 0; 373 return 0;
353 374
354 /* PLL needs to be locked */ 375 /* PLL needs to be locked */
355 val = readl(pll->pll_base + ctrl->status.offset); 376 val = readl(pll->status_base + ctrl->status.offset);
356 if ((val & (1 << ctrl->status.shift)) == 0) { 377 if ((val & (1 << ctrl->status.shift)) == 0) {
357 clk->rate = 0; 378 clk->rate = 0;
358 return 0; 379 return 0;
@@ -363,19 +384,19 @@ static unsigned long iproc_pll_recalc_rate(struct clk_hw *hw,
363 * 384 *
364 * ((ndiv_int + ndiv_frac / 2^20) * (parent clock rate / pdiv) 385 * ((ndiv_int + ndiv_frac / 2^20) * (parent clock rate / pdiv)
365 */ 386 */
366 val = readl(pll->pll_base + ctrl->ndiv_int.offset); 387 val = readl(pll->control_base + ctrl->ndiv_int.offset);
367 ndiv_int = (val >> ctrl->ndiv_int.shift) & 388 ndiv_int = (val >> ctrl->ndiv_int.shift) &
368 bit_mask(ctrl->ndiv_int.width); 389 bit_mask(ctrl->ndiv_int.width);
369 ndiv = ndiv_int << 20; 390 ndiv = ndiv_int << 20;
370 391
371 if (ctrl->flags & IPROC_CLK_PLL_HAS_NDIV_FRAC) { 392 if (ctrl->flags & IPROC_CLK_PLL_HAS_NDIV_FRAC) {
372 val = readl(pll->pll_base + ctrl->ndiv_frac.offset); 393 val = readl(pll->control_base + ctrl->ndiv_frac.offset);
373 ndiv_frac = (val >> ctrl->ndiv_frac.shift) & 394 ndiv_frac = (val >> ctrl->ndiv_frac.shift) &
374 bit_mask(ctrl->ndiv_frac.width); 395 bit_mask(ctrl->ndiv_frac.width);
375 ndiv += ndiv_frac; 396 ndiv += ndiv_frac;
376 } 397 }
377 398
378 val = readl(pll->pll_base + ctrl->pdiv.offset); 399 val = readl(pll->control_base + ctrl->pdiv.offset);
379 pdiv = (val >> ctrl->pdiv.shift) & bit_mask(ctrl->pdiv.width); 400 pdiv = (val >> ctrl->pdiv.shift) & bit_mask(ctrl->pdiv.width);
380 401
381 clk->rate = (ndiv * parent_rate) >> 20; 402 clk->rate = (ndiv * parent_rate) >> 20;
@@ -440,16 +461,14 @@ static int iproc_clk_enable(struct clk_hw *hw)
440 u32 val; 461 u32 val;
441 462
442 /* channel enable is active low */ 463 /* channel enable is active low */
443 val = readl(pll->pll_base + ctrl->enable.offset); 464 val = readl(pll->control_base + ctrl->enable.offset);
444 val &= ~(1 << ctrl->enable.enable_shift); 465 val &= ~(1 << ctrl->enable.enable_shift);
445 writel(val, pll->pll_base + ctrl->enable.offset); 466 iproc_pll_write(pll, pll->control_base, ctrl->enable.offset, val);
446 467
447 /* also make sure channel is not held */ 468 /* also make sure channel is not held */
448 val = readl(pll->pll_base + ctrl->enable.offset); 469 val = readl(pll->control_base + ctrl->enable.offset);
449 val &= ~(1 << ctrl->enable.hold_shift); 470 val &= ~(1 << ctrl->enable.hold_shift);
450 writel(val, pll->pll_base + ctrl->enable.offset); 471 iproc_pll_write(pll, pll->control_base, ctrl->enable.offset, val);
451 if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
452 readl(pll->pll_base + ctrl->enable.offset);
453 472
454 return 0; 473 return 0;
455} 474}
@@ -464,11 +483,9 @@ static void iproc_clk_disable(struct clk_hw *hw)
464 if (ctrl->flags & IPROC_CLK_AON) 483 if (ctrl->flags & IPROC_CLK_AON)
465 return; 484 return;
466 485
467 val = readl(pll->pll_base + ctrl->enable.offset); 486 val = readl(pll->control_base + ctrl->enable.offset);
468 val |= 1 << ctrl->enable.enable_shift; 487 val |= 1 << ctrl->enable.enable_shift;
469 writel(val, pll->pll_base + ctrl->enable.offset); 488 iproc_pll_write(pll, pll->control_base, ctrl->enable.offset, val);
470 if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
471 readl(pll->pll_base + ctrl->enable.offset);
472} 489}
473 490
474static unsigned long iproc_clk_recalc_rate(struct clk_hw *hw, 491static unsigned long iproc_clk_recalc_rate(struct clk_hw *hw,
@@ -483,7 +500,7 @@ static unsigned long iproc_clk_recalc_rate(struct clk_hw *hw,
483 if (parent_rate == 0) 500 if (parent_rate == 0)
484 return 0; 501 return 0;
485 502
486 val = readl(pll->pll_base + ctrl->mdiv.offset); 503 val = readl(pll->control_base + ctrl->mdiv.offset);
487 mdiv = (val >> ctrl->mdiv.shift) & bit_mask(ctrl->mdiv.width); 504 mdiv = (val >> ctrl->mdiv.shift) & bit_mask(ctrl->mdiv.width);
488 if (mdiv == 0) 505 if (mdiv == 0)
489 mdiv = 256; 506 mdiv = 256;
@@ -530,16 +547,14 @@ static int iproc_clk_set_rate(struct clk_hw *hw, unsigned long rate,
530 if (div > 256) 547 if (div > 256)
531 return -EINVAL; 548 return -EINVAL;
532 549
533 val = readl(pll->pll_base + ctrl->mdiv.offset); 550 val = readl(pll->control_base + ctrl->mdiv.offset);
534 if (div == 256) { 551 if (div == 256) {
535 val &= ~(bit_mask(ctrl->mdiv.width) << ctrl->mdiv.shift); 552 val &= ~(bit_mask(ctrl->mdiv.width) << ctrl->mdiv.shift);
536 } else { 553 } else {
537 val &= ~(bit_mask(ctrl->mdiv.width) << ctrl->mdiv.shift); 554 val &= ~(bit_mask(ctrl->mdiv.width) << ctrl->mdiv.shift);
538 val |= div << ctrl->mdiv.shift; 555 val |= div << ctrl->mdiv.shift;
539 } 556 }
540 writel(val, pll->pll_base + ctrl->mdiv.offset); 557 iproc_pll_write(pll, pll->control_base, ctrl->mdiv.offset, val);
541 if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
542 readl(pll->pll_base + ctrl->mdiv.offset);
543 clk->rate = parent_rate / div; 558 clk->rate = parent_rate / div;
544 559
545 return 0; 560 return 0;
@@ -564,11 +579,10 @@ static void iproc_pll_sw_cfg(struct iproc_pll *pll)
564 if (ctrl->flags & IPROC_CLK_PLL_NEEDS_SW_CFG) { 579 if (ctrl->flags & IPROC_CLK_PLL_NEEDS_SW_CFG) {
565 u32 val; 580 u32 val;
566 581
567 val = readl(pll->pll_base + ctrl->sw_ctrl.offset); 582 val = readl(pll->control_base + ctrl->sw_ctrl.offset);
568 val |= BIT(ctrl->sw_ctrl.shift); 583 val |= BIT(ctrl->sw_ctrl.shift);
569 writel(val, pll->pll_base + ctrl->sw_ctrl.offset); 584 iproc_pll_write(pll, pll->control_base, ctrl->sw_ctrl.offset,
570 if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK)) 585 val);
571 readl(pll->pll_base + ctrl->sw_ctrl.offset);
572 } 586 }
573} 587}
574 588
@@ -603,13 +617,12 @@ void __init iproc_pll_clk_setup(struct device_node *node,
603 if (WARN_ON(!pll->clks)) 617 if (WARN_ON(!pll->clks))
604 goto err_clks; 618 goto err_clks;
605 619
606 pll->pll_base = of_iomap(node, 0); 620 pll->control_base = of_iomap(node, 0);
607 if (WARN_ON(!pll->pll_base)) 621 if (WARN_ON(!pll->control_base))
608 goto err_pll_iomap; 622 goto err_pll_iomap;
609 623
624 /* Some SoCs do not require the pwr_base, thus failing is not fatal */
610 pll->pwr_base = of_iomap(node, 1); 625 pll->pwr_base = of_iomap(node, 1);
611 if (WARN_ON(!pll->pwr_base))
612 goto err_pwr_iomap;
613 626
614 /* some PLLs require gating control at the top ASIU level */ 627 /* some PLLs require gating control at the top ASIU level */
615 if (pll_ctrl->flags & IPROC_CLK_PLL_ASIU) { 628 if (pll_ctrl->flags & IPROC_CLK_PLL_ASIU) {
@@ -618,6 +631,16 @@ void __init iproc_pll_clk_setup(struct device_node *node,
618 goto err_asiu_iomap; 631 goto err_asiu_iomap;
619 } 632 }
620 633
634 if (pll_ctrl->flags & IPROC_CLK_PLL_SPLIT_STAT_CTRL) {
635 /* Some SoCs have a split status/control. If this does not
636 * exist, assume they are unified.
637 */
638 pll->status_base = of_iomap(node, 2);
639 if (!pll->status_base)
640 goto err_status_iomap;
641 } else
642 pll->status_base = pll->control_base;
643
621 /* initialize and register the PLL itself */ 644 /* initialize and register the PLL itself */
622 pll->ctrl = pll_ctrl; 645 pll->ctrl = pll_ctrl;
623 646
@@ -688,14 +711,18 @@ err_clk_register:
688 clk_unregister(pll->clk_data.clks[i]); 711 clk_unregister(pll->clk_data.clks[i]);
689 712
690err_pll_register: 713err_pll_register:
714 if (pll->status_base != pll->control_base)
715 iounmap(pll->status_base);
716
717err_status_iomap:
691 if (pll->asiu_base) 718 if (pll->asiu_base)
692 iounmap(pll->asiu_base); 719 iounmap(pll->asiu_base);
693 720
694err_asiu_iomap: 721err_asiu_iomap:
695 iounmap(pll->pwr_base); 722 if (pll->pwr_base)
723 iounmap(pll->pwr_base);
696 724
697err_pwr_iomap: 725 iounmap(pll->control_base);
698 iounmap(pll->pll_base);
699 726
700err_pll_iomap: 727err_pll_iomap:
701 kfree(pll->clks); 728 kfree(pll->clks);
diff --git a/drivers/clk/bcm/clk-iproc.h b/drivers/clk/bcm/clk-iproc.h
index d834b7abd5c6..8988de70a98c 100644
--- a/drivers/clk/bcm/clk-iproc.h
+++ b/drivers/clk/bcm/clk-iproc.h
@@ -49,6 +49,18 @@
49#define IPROC_CLK_PLL_NEEDS_SW_CFG BIT(4) 49#define IPROC_CLK_PLL_NEEDS_SW_CFG BIT(4)
50 50
51/* 51/*
52 * Some PLLs use a different way to control clock power, via the PWRDWN bit in
53 * the PLL control register
54 */
55#define IPROC_CLK_EMBED_PWRCTRL BIT(5)
56
57/*
58 * Some PLLs have separate registers for Status and Control. Identify this to
59 * let the driver know if additional registers need to be used
60 */
61#define IPROC_CLK_PLL_SPLIT_STAT_CTRL BIT(6)
62
63/*
52 * Parameters for VCO frequency configuration 64 * Parameters for VCO frequency configuration
53 * 65 *
54 * VCO frequency = 66 * VCO frequency =
@@ -88,12 +100,19 @@ struct iproc_pll_aon_pwr_ctrl {
88}; 100};
89 101
90/* 102/*
91 * Control of the PLL reset, with Ki, Kp, and Ka parameters 103 * Control of the PLL reset
92 */ 104 */
93struct iproc_pll_reset_ctrl { 105struct iproc_pll_reset_ctrl {
94 unsigned int offset; 106 unsigned int offset;
95 unsigned int reset_shift; 107 unsigned int reset_shift;
96 unsigned int p_reset_shift; 108 unsigned int p_reset_shift;
109};
110
111/*
112 * Control of the Ki, Kp, and Ka parameters
113 */
114struct iproc_pll_dig_filter_ctrl {
115 unsigned int offset;
97 unsigned int ki_shift; 116 unsigned int ki_shift;
98 unsigned int ki_width; 117 unsigned int ki_width;
99 unsigned int kp_shift; 118 unsigned int kp_shift;
@@ -123,6 +142,7 @@ struct iproc_pll_ctrl {
123 struct iproc_pll_aon_pwr_ctrl aon; 142 struct iproc_pll_aon_pwr_ctrl aon;
124 struct iproc_asiu_gate asiu; 143 struct iproc_asiu_gate asiu;
125 struct iproc_pll_reset_ctrl reset; 144 struct iproc_pll_reset_ctrl reset;
145 struct iproc_pll_dig_filter_ctrl dig_filter;
126 struct iproc_pll_sw_ctrl sw_ctrl; 146 struct iproc_pll_sw_ctrl sw_ctrl;
127 struct iproc_clk_reg_op ndiv_int; 147 struct iproc_clk_reg_op ndiv_int;
128 struct iproc_clk_reg_op ndiv_frac; 148 struct iproc_clk_reg_op ndiv_frac;
diff --git a/drivers/clk/bcm/clk-ns2.c b/drivers/clk/bcm/clk-ns2.c
new file mode 100644
index 000000000000..a564e9248814
--- /dev/null
+++ b/drivers/clk/bcm/clk-ns2.c
@@ -0,0 +1,288 @@
1/*
2 * Copyright (C) 2015 Broadcom Corporation
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation version 2.
7 *
8 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
9 * kind, whether express or implied; without even the implied warranty
10 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include <linux/kernel.h>
15#include <linux/err.h>
16#include <linux/clk-provider.h>
17#include <linux/io.h>
18#include <linux/of.h>
19#include <linux/of_address.h>
20
21#include <dt-bindings/clock/bcm-ns2.h>
22#include "clk-iproc.h"
23
24#define REG_VAL(o, s, w) { .offset = o, .shift = s, .width = w, }
25
26#define AON_VAL(o, pw, ps, is) { .offset = o, .pwr_width = pw, \
27 .pwr_shift = ps, .iso_shift = is }
28
29#define RESET_VAL(o, rs, prs) { .offset = o, .reset_shift = rs, \
30 .p_reset_shift = prs }
31
32#define DF_VAL(o, kis, kiw, kps, kpw, kas, kaw) { .offset = o, .ki_shift = kis,\
33 .ki_width = kiw, .kp_shift = kps, .kp_width = kpw, .ka_shift = kas, \
34 .ka_width = kaw }
35
36#define VCO_CTRL_VAL(uo, lo) { .u_offset = uo, .l_offset = lo }
37
38#define ENABLE_VAL(o, es, hs, bs) { .offset = o, .enable_shift = es, \
39 .hold_shift = hs, .bypass_shift = bs }
40
41static const struct iproc_pll_ctrl genpll_scr = {
42 .flags = IPROC_CLK_AON | IPROC_CLK_PLL_SPLIT_STAT_CTRL,
43 .aon = AON_VAL(0x0, 1, 15, 12),
44 .reset = RESET_VAL(0x4, 2, 1),
45 .dig_filter = DF_VAL(0x0, 9, 3, 5, 4, 2, 3),
46 .ndiv_int = REG_VAL(0x8, 4, 10),
47 .pdiv = REG_VAL(0x8, 0, 4),
48 .vco_ctrl = VCO_CTRL_VAL(0x10, 0xc),
49 .status = REG_VAL(0x0, 27, 1),
50};
51
52
53static const struct iproc_clk_ctrl genpll_scr_clk[] = {
54 /* bypass_shift, the last value passed into ENABLE_VAL(), is not defined
55 * in NS2. However, it doesn't appear to be used anywhere, so setting
56 * it to 0.
57 */
58 [BCM_NS2_GENPLL_SCR_SCR_CLK] = {
59 .channel = BCM_NS2_GENPLL_SCR_SCR_CLK,
60 .flags = IPROC_CLK_AON,
61 .enable = ENABLE_VAL(0x0, 18, 12, 0),
62 .mdiv = REG_VAL(0x18, 0, 8),
63 },
64 [BCM_NS2_GENPLL_SCR_FS_CLK] = {
65 .channel = BCM_NS2_GENPLL_SCR_FS_CLK,
66 .flags = IPROC_CLK_AON,
67 .enable = ENABLE_VAL(0x0, 19, 13, 0),
68 .mdiv = REG_VAL(0x18, 8, 8),
69 },
70 [BCM_NS2_GENPLL_SCR_AUDIO_CLK] = {
71 .channel = BCM_NS2_GENPLL_SCR_AUDIO_CLK,
72 .flags = IPROC_CLK_AON,
73 .enable = ENABLE_VAL(0x0, 20, 14, 0),
74 .mdiv = REG_VAL(0x14, 0, 8),
75 },
76 [BCM_NS2_GENPLL_SCR_CH3_UNUSED] = {
77 .channel = BCM_NS2_GENPLL_SCR_CH3_UNUSED,
78 .flags = IPROC_CLK_AON,
79 .enable = ENABLE_VAL(0x0, 21, 15, 0),
80 .mdiv = REG_VAL(0x14, 8, 8),
81 },
82 [BCM_NS2_GENPLL_SCR_CH4_UNUSED] = {
83 .channel = BCM_NS2_GENPLL_SCR_CH4_UNUSED,
84 .flags = IPROC_CLK_AON,
85 .enable = ENABLE_VAL(0x0, 22, 16, 0),
86 .mdiv = REG_VAL(0x14, 16, 8),
87 },
88 [BCM_NS2_GENPLL_SCR_CH5_UNUSED] = {
89 .channel = BCM_NS2_GENPLL_SCR_CH5_UNUSED,
90 .flags = IPROC_CLK_AON,
91 .enable = ENABLE_VAL(0x0, 23, 17, 0),
92 .mdiv = REG_VAL(0x14, 24, 8),
93 },
94};
95
96static void __init ns2_genpll_scr_clk_init(struct device_node *node)
97{
98 iproc_pll_clk_setup(node, &genpll_scr, NULL, 0, genpll_scr_clk,
99 ARRAY_SIZE(genpll_scr_clk));
100}
101CLK_OF_DECLARE(ns2_genpll_src_clk, "brcm,ns2-genpll-scr",
102 ns2_genpll_scr_clk_init);
103
104static const struct iproc_pll_ctrl genpll_sw = {
105 .flags = IPROC_CLK_AON | IPROC_CLK_PLL_SPLIT_STAT_CTRL,
106 .aon = AON_VAL(0x0, 2, 9, 8),
107 .reset = RESET_VAL(0x4, 2, 1),
108 .dig_filter = DF_VAL(0x0, 9, 3, 5, 4, 2, 3),
109 .ndiv_int = REG_VAL(0x8, 4, 10),
110 .pdiv = REG_VAL(0x8, 0, 4),
111 .vco_ctrl = VCO_CTRL_VAL(0x10, 0xc),
112 .status = REG_VAL(0x0, 13, 1),
113};
114
115static const struct iproc_clk_ctrl genpll_sw_clk[] = {
116 /* bypass_shift, the last value passed into ENABLE_VAL(), is not defined
117 * in NS2. However, it doesn't appear to be used anywhere, so setting
118 * it to 0.
119 */
120 [BCM_NS2_GENPLL_SW_RPE_CLK] = {
121 .channel = BCM_NS2_GENPLL_SW_RPE_CLK,
122 .flags = IPROC_CLK_AON,
123 .enable = ENABLE_VAL(0x0, 18, 12, 0),
124 .mdiv = REG_VAL(0x18, 0, 8),
125 },
126 [BCM_NS2_GENPLL_SW_250_CLK] = {
127 .channel = BCM_NS2_GENPLL_SW_250_CLK,
128 .flags = IPROC_CLK_AON,
129 .enable = ENABLE_VAL(0x0, 19, 13, 0),
130 .mdiv = REG_VAL(0x18, 8, 8),
131 },
132 [BCM_NS2_GENPLL_SW_NIC_CLK] = {
133 .channel = BCM_NS2_GENPLL_SW_NIC_CLK,
134 .flags = IPROC_CLK_AON,
135 .enable = ENABLE_VAL(0x0, 20, 14, 0),
136 .mdiv = REG_VAL(0x14, 0, 8),
137 },
138 [BCM_NS2_GENPLL_SW_CHIMP_CLK] = {
139 .channel = BCM_NS2_GENPLL_SW_CHIMP_CLK,
140 .flags = IPROC_CLK_AON,
141 .enable = ENABLE_VAL(0x0, 21, 15, 0),
142 .mdiv = REG_VAL(0x14, 8, 8),
143 },
144 [BCM_NS2_GENPLL_SW_PORT_CLK] = {
145 .channel = BCM_NS2_GENPLL_SW_PORT_CLK,
146 .flags = IPROC_CLK_AON,
147 .enable = ENABLE_VAL(0x0, 22, 16, 0),
148 .mdiv = REG_VAL(0x14, 16, 8),
149 },
150 [BCM_NS2_GENPLL_SW_SDIO_CLK] = {
151 .channel = BCM_NS2_GENPLL_SW_SDIO_CLK,
152 .flags = IPROC_CLK_AON,
153 .enable = ENABLE_VAL(0x0, 23, 17, 0),
154 .mdiv = REG_VAL(0x14, 24, 8),
155 },
156};
157
158static void __init ns2_genpll_sw_clk_init(struct device_node *node)
159{
160 iproc_pll_clk_setup(node, &genpll_sw, NULL, 0, genpll_sw_clk,
161 ARRAY_SIZE(genpll_sw_clk));
162}
163CLK_OF_DECLARE(ns2_genpll_sw_clk, "brcm,ns2-genpll-sw",
164 ns2_genpll_sw_clk_init);
165
166static const struct iproc_pll_ctrl lcpll_ddr = {
167 .flags = IPROC_CLK_AON | IPROC_CLK_PLL_SPLIT_STAT_CTRL,
168 .aon = AON_VAL(0x0, 2, 1, 0),
169 .reset = RESET_VAL(0x4, 2, 1),
170 .dig_filter = DF_VAL(0x0, 9, 3, 5, 4, 1, 4),
171 .ndiv_int = REG_VAL(0x8, 4, 10),
172 .pdiv = REG_VAL(0x8, 0, 4),
173 .vco_ctrl = VCO_CTRL_VAL(0x10, 0xc),
174 .status = REG_VAL(0x0, 0, 1),
175};
176
177static const struct iproc_clk_ctrl lcpll_ddr_clk[] = {
178 /* bypass_shift, the last value passed into ENABLE_VAL(), is not defined
179 * in NS2. However, it doesn't appear to be used anywhere, so setting
180 * it to 0.
181 */
182 [BCM_NS2_LCPLL_DDR_PCIE_SATA_USB_CLK] = {
183 .channel = BCM_NS2_LCPLL_DDR_PCIE_SATA_USB_CLK,
184 .flags = IPROC_CLK_AON,
185 .enable = ENABLE_VAL(0x0, 18, 12, 0),
186 .mdiv = REG_VAL(0x14, 0, 8),
187 },
188 [BCM_NS2_LCPLL_DDR_DDR_CLK] = {
189 .channel = BCM_NS2_LCPLL_DDR_DDR_CLK,
190 .flags = IPROC_CLK_AON,
191 .enable = ENABLE_VAL(0x0, 19, 13, 0),
192 .mdiv = REG_VAL(0x14, 8, 8),
193 },
194 [BCM_NS2_LCPLL_DDR_CH2_UNUSED] = {
195 .channel = BCM_NS2_LCPLL_DDR_CH2_UNUSED,
196 .flags = IPROC_CLK_AON,
197 .enable = ENABLE_VAL(0x0, 20, 14, 0),
198 .mdiv = REG_VAL(0x10, 0, 8),
199 },
200 [BCM_NS2_LCPLL_DDR_CH3_UNUSED] = {
201 .channel = BCM_NS2_LCPLL_DDR_CH3_UNUSED,
202 .flags = IPROC_CLK_AON,
203 .enable = ENABLE_VAL(0x0, 21, 15, 0),
204 .mdiv = REG_VAL(0x10, 8, 8),
205 },
206 [BCM_NS2_LCPLL_DDR_CH4_UNUSED] = {
207 .channel = BCM_NS2_LCPLL_DDR_CH4_UNUSED,
208 .flags = IPROC_CLK_AON,
209 .enable = ENABLE_VAL(0x0, 22, 16, 0),
210 .mdiv = REG_VAL(0x10, 16, 8),
211 },
212 [BCM_NS2_LCPLL_DDR_CH5_UNUSED] = {
213 .channel = BCM_NS2_LCPLL_DDR_CH5_UNUSED,
214 .flags = IPROC_CLK_AON,
215 .enable = ENABLE_VAL(0x0, 23, 17, 0),
216 .mdiv = REG_VAL(0x10, 24, 8),
217 },
218};
219
220static void __init ns2_lcpll_ddr_clk_init(struct device_node *node)
221{
222 iproc_pll_clk_setup(node, &lcpll_ddr, NULL, 0, lcpll_ddr_clk,
223 ARRAY_SIZE(lcpll_ddr_clk));
224}
225CLK_OF_DECLARE(ns2_lcpll_ddr_clk, "brcm,ns2-lcpll-ddr",
226 ns2_lcpll_ddr_clk_init);
227
228static const struct iproc_pll_ctrl lcpll_ports = {
229 .flags = IPROC_CLK_AON | IPROC_CLK_PLL_SPLIT_STAT_CTRL,
230 .aon = AON_VAL(0x0, 2, 5, 4),
231 .reset = RESET_VAL(0x4, 2, 1),
232 .dig_filter = DF_VAL(0x0, 9, 3, 5, 4, 1, 4),
233 .ndiv_int = REG_VAL(0x8, 4, 10),
234 .pdiv = REG_VAL(0x8, 0, 4),
235 .vco_ctrl = VCO_CTRL_VAL(0x10, 0xc),
236 .status = REG_VAL(0x0, 0, 1),
237};
238
239static const struct iproc_clk_ctrl lcpll_ports_clk[] = {
240 /* bypass_shift, the last value passed into ENABLE_VAL(), is not defined
241 * in NS2. However, it doesn't appear to be used anywhere, so setting
242 * it to 0.
243 */
244 [BCM_NS2_LCPLL_PORTS_WAN_CLK] = {
245 .channel = BCM_NS2_LCPLL_PORTS_WAN_CLK,
246 .flags = IPROC_CLK_AON,
247 .enable = ENABLE_VAL(0x0, 18, 12, 0),
248 .mdiv = REG_VAL(0x14, 0, 8),
249 },
250 [BCM_NS2_LCPLL_PORTS_RGMII_CLK] = {
251 .channel = BCM_NS2_LCPLL_PORTS_RGMII_CLK,
252 .flags = IPROC_CLK_AON,
253 .enable = ENABLE_VAL(0x0, 19, 13, 0),
254 .mdiv = REG_VAL(0x14, 8, 8),
255 },
256 [BCM_NS2_LCPLL_PORTS_CH2_UNUSED] = {
257 .channel = BCM_NS2_LCPLL_PORTS_CH2_UNUSED,
258 .flags = IPROC_CLK_AON,
259 .enable = ENABLE_VAL(0x0, 20, 14, 0),
260 .mdiv = REG_VAL(0x10, 0, 8),
261 },
262 [BCM_NS2_LCPLL_PORTS_CH3_UNUSED] = {
263 .channel = BCM_NS2_LCPLL_PORTS_CH3_UNUSED,
264 .flags = IPROC_CLK_AON,
265 .enable = ENABLE_VAL(0x0, 21, 15, 0),
266 .mdiv = REG_VAL(0x10, 8, 8),
267 },
268 [BCM_NS2_LCPLL_PORTS_CH4_UNUSED] = {
269 .channel = BCM_NS2_LCPLL_PORTS_CH4_UNUSED,
270 .flags = IPROC_CLK_AON,
271 .enable = ENABLE_VAL(0x0, 22, 16, 0),
272 .mdiv = REG_VAL(0x10, 16, 8),
273 },
274 [BCM_NS2_LCPLL_PORTS_CH5_UNUSED] = {
275 .channel = BCM_NS2_LCPLL_PORTS_CH5_UNUSED,
276 .flags = IPROC_CLK_AON,
277 .enable = ENABLE_VAL(0x0, 23, 17, 0),
278 .mdiv = REG_VAL(0x10, 24, 8),
279 },
280};
281
282static void __init ns2_lcpll_ports_clk_init(struct device_node *node)
283{
284 iproc_pll_clk_setup(node, &lcpll_ports, NULL, 0, lcpll_ports_clk,
285 ARRAY_SIZE(lcpll_ports_clk));
286}
287CLK_OF_DECLARE(ns2_lcpll_ports_clk, "brcm,ns2-lcpll-ports",
288 ns2_lcpll_ports_clk_init);
diff --git a/drivers/clk/bcm/clk-nsp.c b/drivers/clk/bcm/clk-nsp.c
new file mode 100644
index 000000000000..cf66f640a47d
--- /dev/null
+++ b/drivers/clk/bcm/clk-nsp.c
@@ -0,0 +1,139 @@
1/*
2 * Copyright (C) 2015 Broadcom Corporation
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation version 2.
7 *
8 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
9 * kind, whether express or implied; without even the implied warranty
10 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include <linux/kernel.h>
15#include <linux/err.h>
16#include <linux/clk-provider.h>
17#include <linux/io.h>
18#include <linux/of.h>
19#include <linux/of_address.h>
20
21#include <dt-bindings/clock/bcm-nsp.h>
22#include "clk-iproc.h"
23
24#define REG_VAL(o, s, w) { .offset = o, .shift = s, .width = w, }
25
26#define AON_VAL(o, pw, ps, is) { .offset = o, .pwr_width = pw, \
27 .pwr_shift = ps, .iso_shift = is }
28
29#define RESET_VAL(o, rs, prs) { .offset = o, .reset_shift = rs, \
30 .p_reset_shift = prs }
31
32#define DF_VAL(o, kis, kiw, kps, kpw, kas, kaw) { .offset = o, .ki_shift = kis,\
33 .ki_width = kiw, .kp_shift = kps, .kp_width = kpw, .ka_shift = kas, \
34 .ka_width = kaw }
35
36#define ENABLE_VAL(o, es, hs, bs) { .offset = o, .enable_shift = es, \
37 .hold_shift = hs, .bypass_shift = bs }
38
39static void __init nsp_armpll_init(struct device_node *node)
40{
41 iproc_armpll_setup(node);
42}
43CLK_OF_DECLARE(nsp_armpll, "brcm,nsp-armpll", nsp_armpll_init);
44
45static const struct iproc_pll_ctrl genpll = {
46 .flags = IPROC_CLK_PLL_HAS_NDIV_FRAC | IPROC_CLK_EMBED_PWRCTRL,
47 .aon = AON_VAL(0x0, 1, 12, 0),
48 .reset = RESET_VAL(0x0, 11, 10),
49 .dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 3),
50 .ndiv_int = REG_VAL(0x14, 20, 10),
51 .ndiv_frac = REG_VAL(0x14, 0, 20),
52 .pdiv = REG_VAL(0x18, 24, 3),
53 .status = REG_VAL(0x20, 12, 1),
54};
55
56static const struct iproc_clk_ctrl genpll_clk[] = {
57 [BCM_NSP_GENPLL_PHY_CLK] = {
58 .channel = BCM_NSP_GENPLL_PHY_CLK,
59 .flags = IPROC_CLK_AON,
60 .enable = ENABLE_VAL(0x4, 12, 6, 18),
61 .mdiv = REG_VAL(0x18, 16, 8),
62 },
63 [BCM_NSP_GENPLL_ENET_SW_CLK] = {
64 .channel = BCM_NSP_GENPLL_ENET_SW_CLK,
65 .flags = IPROC_CLK_AON,
66 .enable = ENABLE_VAL(0x4, 13, 7, 19),
67 .mdiv = REG_VAL(0x18, 8, 8),
68 },
69 [BCM_NSP_GENPLL_USB_PHY_REF_CLK] = {
70 .channel = BCM_NSP_GENPLL_USB_PHY_REF_CLK,
71 .flags = IPROC_CLK_AON,
72 .enable = ENABLE_VAL(0x4, 14, 8, 20),
73 .mdiv = REG_VAL(0x18, 0, 8),
74 },
75 [BCM_NSP_GENPLL_IPROCFAST_CLK] = {
76 .channel = BCM_NSP_GENPLL_IPROCFAST_CLK,
77 .flags = IPROC_CLK_AON,
78 .enable = ENABLE_VAL(0x4, 15, 9, 21),
79 .mdiv = REG_VAL(0x1c, 16, 8),
80 },
81 [BCM_NSP_GENPLL_SATA1_CLK] = {
82 .channel = BCM_NSP_GENPLL_SATA1_CLK,
83 .flags = IPROC_CLK_AON,
84 .enable = ENABLE_VAL(0x4, 16, 10, 22),
85 .mdiv = REG_VAL(0x1c, 8, 8),
86 },
87 [BCM_NSP_GENPLL_SATA2_CLK] = {
88 .channel = BCM_NSP_GENPLL_SATA2_CLK,
89 .flags = IPROC_CLK_AON,
90 .enable = ENABLE_VAL(0x4, 17, 11, 23),
91 .mdiv = REG_VAL(0x1c, 0, 8),
92 },
93};
94
95static void __init nsp_genpll_clk_init(struct device_node *node)
96{
97 iproc_pll_clk_setup(node, &genpll, NULL, 0, genpll_clk,
98 ARRAY_SIZE(genpll_clk));
99}
100CLK_OF_DECLARE(nsp_genpll_clk, "brcm,nsp-genpll", nsp_genpll_clk_init);
101
102static const struct iproc_pll_ctrl lcpll0 = {
103 .flags = IPROC_CLK_PLL_HAS_NDIV_FRAC | IPROC_CLK_EMBED_PWRCTRL,
104 .aon = AON_VAL(0x0, 1, 24, 0),
105 .reset = RESET_VAL(0x0, 23, 22),
106 .dig_filter = DF_VAL(0x0, 16, 3, 12, 4, 19, 4),
107 .ndiv_int = REG_VAL(0x4, 20, 8),
108 .ndiv_frac = REG_VAL(0x4, 0, 20),
109 .pdiv = REG_VAL(0x4, 28, 3),
110 .status = REG_VAL(0x10, 12, 1),
111};
112
113static const struct iproc_clk_ctrl lcpll0_clk[] = {
114 [BCM_NSP_LCPLL0_PCIE_PHY_REF_CLK] = {
115 .channel = BCM_NSP_LCPLL0_PCIE_PHY_REF_CLK,
116 .flags = IPROC_CLK_AON,
117 .enable = ENABLE_VAL(0x0, 6, 3, 9),
118 .mdiv = REG_VAL(0x8, 24, 8),
119 },
120 [BCM_NSP_LCPLL0_SDIO_CLK] = {
121 .channel = BCM_NSP_LCPLL0_SDIO_CLK,
122 .flags = IPROC_CLK_AON,
123 .enable = ENABLE_VAL(0x0, 7, 4, 10),
124 .mdiv = REG_VAL(0x8, 16, 8),
125 },
126 [BCM_NSP_LCPLL0_DDR_PHY_CLK] = {
127 .channel = BCM_NSP_LCPLL0_DDR_PHY_CLK,
128 .flags = IPROC_CLK_AON,
129 .enable = ENABLE_VAL(0x0, 8, 5, 11),
130 .mdiv = REG_VAL(0x8, 8, 8),
131 },
132};
133
134static void __init nsp_lcpll0_clk_init(struct device_node *node)
135{
136 iproc_pll_clk_setup(node, &lcpll0, NULL, 0, lcpll0_clk,
137 ARRAY_SIZE(lcpll0_clk));
138}
139CLK_OF_DECLARE(nsp_lcpll0_clk, "brcm,nsp-lcpll0", nsp_lcpll0_clk_init);
diff --git a/include/dt-bindings/clock/bcm-ns2.h b/include/dt-bindings/clock/bcm-ns2.h
new file mode 100644
index 000000000000..d99c7a2e70cb
--- /dev/null
+++ b/include/dt-bindings/clock/bcm-ns2.h
@@ -0,0 +1,72 @@
1/*
2 * BSD LICENSE
3 *
4 * Copyright(c) 2015 Broadcom Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Broadcom Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#ifndef _CLOCK_BCM_NS2_H
34#define _CLOCK_BCM_NS2_H
35
36/* GENPLL SCR clock channel ID */
37#define BCM_NS2_GENPLL_SCR 0
38#define BCM_NS2_GENPLL_SCR_SCR_CLK 1
39#define BCM_NS2_GENPLL_SCR_FS_CLK 2
40#define BCM_NS2_GENPLL_SCR_AUDIO_CLK 3
41#define BCM_NS2_GENPLL_SCR_CH3_UNUSED 4
42#define BCM_NS2_GENPLL_SCR_CH4_UNUSED 5
43#define BCM_NS2_GENPLL_SCR_CH5_UNUSED 6
44
45/* GENPLL SW clock channel ID */
46#define BCM_NS2_GENPLL_SW 0
47#define BCM_NS2_GENPLL_SW_RPE_CLK 1
48#define BCM_NS2_GENPLL_SW_250_CLK 2
49#define BCM_NS2_GENPLL_SW_NIC_CLK 3
50#define BCM_NS2_GENPLL_SW_CHIMP_CLK 4
51#define BCM_NS2_GENPLL_SW_PORT_CLK 5
52#define BCM_NS2_GENPLL_SW_SDIO_CLK 6
53
54/* LCPLL DDR clock channel ID */
55#define BCM_NS2_LCPLL_DDR 0
56#define BCM_NS2_LCPLL_DDR_PCIE_SATA_USB_CLK 1
57#define BCM_NS2_LCPLL_DDR_DDR_CLK 2
58#define BCM_NS2_LCPLL_DDR_CH2_UNUSED 3
59#define BCM_NS2_LCPLL_DDR_CH3_UNUSED 4
60#define BCM_NS2_LCPLL_DDR_CH4_UNUSED 5
61#define BCM_NS2_LCPLL_DDR_CH5_UNUSED 6
62
63/* LCPLL PORTS clock channel ID */
64#define BCM_NS2_LCPLL_PORTS 0
65#define BCM_NS2_LCPLL_PORTS_WAN_CLK 1
66#define BCM_NS2_LCPLL_PORTS_RGMII_CLK 2
67#define BCM_NS2_LCPLL_PORTS_CH2_UNUSED 3
68#define BCM_NS2_LCPLL_PORTS_CH3_UNUSED 4
69#define BCM_NS2_LCPLL_PORTS_CH4_UNUSED 5
70#define BCM_NS2_LCPLL_PORTS_CH5_UNUSED 6
71
72#endif /* _CLOCK_BCM_NS2_H */
diff --git a/include/dt-bindings/clock/bcm-nsp.h b/include/dt-bindings/clock/bcm-nsp.h
new file mode 100644
index 000000000000..ad5827cde782
--- /dev/null
+++ b/include/dt-bindings/clock/bcm-nsp.h
@@ -0,0 +1,51 @@
1/*
2 * BSD LICENSE
3 *
4 * Copyright(c) 2015 Broadcom Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Broadcom Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#ifndef _CLOCK_BCM_NSP_H
34#define _CLOCK_BCM_NSP_H
35
36/* GENPLL clock channel ID */
37#define BCM_NSP_GENPLL 0
38#define BCM_NSP_GENPLL_PHY_CLK 1
39#define BCM_NSP_GENPLL_ENET_SW_CLK 2
40#define BCM_NSP_GENPLL_USB_PHY_REF_CLK 3
41#define BCM_NSP_GENPLL_IPROCFAST_CLK 4
42#define BCM_NSP_GENPLL_SATA1_CLK 5
43#define BCM_NSP_GENPLL_SATA2_CLK 6
44
45/* LCPLL0 clock channel ID */
46#define BCM_NSP_LCPLL0 0
47#define BCM_NSP_LCPLL0_PCIE_PHY_REF_CLK 1
48#define BCM_NSP_LCPLL0_SDIO_CLK 2
49#define BCM_NSP_LCPLL0_DDR_PHY_CLK 3
50
51#endif /* _CLOCK_BCM_NSP_H */