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, 1, 11, 10),
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);
289