1/*-
2 * Copyright (c) 2013 Adrian Chadd <adrian@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD$");
29
30#include "opt_ddb.h"
31
32#include <sys/param.h>
33#include <sys/conf.h>
34#include <sys/kernel.h>
35#include <sys/systm.h>
36#include <sys/bus.h>
37#include <sys/cons.h>
38#include <sys/kdb.h>
39#include <sys/reboot.h>
40
41#include <vm/vm.h>
42#include <vm/vm_page.h>
43
44#include <net/ethernet.h>
45
46#include <machine/clock.h>
47#include <machine/cpu.h>
48#include <machine/cpuregs.h>
49#include <machine/hwfunc.h>
50#include <machine/md_var.h>
51#include <machine/trap.h>
52#include <machine/vmparam.h>
53
54#include <mips/atheros/ar71xxreg.h>
55#include <mips/atheros/ar934xreg.h>
56
57#include <mips/atheros/ar71xx_cpudef.h>
58#include <mips/atheros/ar71xx_setup.h>
59
60#include <mips/atheros/ar71xx_chip.h>
61#include <mips/atheros/ar934x_chip.h>
62
63static void
64ar934x_chip_detect_mem_size(void)
65{
66}
67
68static uint32_t
69ar934x_get_pll_freq(uint32_t ref, uint32_t ref_div, uint32_t nint,
70    uint32_t nfrac, uint32_t frac, uint32_t out_div)
71{
72	uint64_t t;
73	uint32_t ret;
74
75	t = u_ar71xx_refclk;
76	t *= nint;
77	t = t / ref_div;
78	ret = t;
79
80	t = u_ar71xx_refclk;
81	t *= nfrac;
82	t = t / (ref_div * frac);
83	ret += t;
84
85	ret /= (1 << out_div);
86	return (ret);
87}
88
89static void
90ar934x_chip_detect_sys_frequency(void)
91{
92	uint32_t pll, out_div, ref_div, nint, nfrac, frac, clk_ctrl, postdiv;
93	uint32_t cpu_pll, ddr_pll;
94	uint32_t bootstrap;
95
96	bootstrap = ATH_READ_REG(AR934X_RESET_REG_BOOTSTRAP);
97	if (bootstrap & AR934X_BOOTSTRAP_REF_CLK_40)
98		u_ar71xx_refclk = 40 * 1000 * 1000;
99	else
100		u_ar71xx_refclk = 25 * 1000 * 1000;
101
102	pll = ATH_READ_REG(AR934X_SRIF_CPU_DPLL2_REG);
103	if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) {
104		out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) &
105		    AR934X_SRIF_DPLL2_OUTDIV_MASK;
106		pll = ATH_READ_REG(AR934X_SRIF_CPU_DPLL1_REG);
107		nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) &
108		    AR934X_SRIF_DPLL1_NINT_MASK;
109		nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK;
110		ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) &
111		    AR934X_SRIF_DPLL1_REFDIV_MASK;
112		frac = 1 << 18;
113	} else {
114		pll = ATH_READ_REG(AR934X_PLL_CPU_CONFIG_REG);
115		out_div = (pll >> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
116			AR934X_PLL_CPU_CONFIG_OUTDIV_MASK;
117		ref_div = (pll >> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
118			  AR934X_PLL_CPU_CONFIG_REFDIV_MASK;
119		nint = (pll >> AR934X_PLL_CPU_CONFIG_NINT_SHIFT) &
120		       AR934X_PLL_CPU_CONFIG_NINT_MASK;
121		nfrac = (pll >> AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT) &
122			AR934X_PLL_CPU_CONFIG_NFRAC_MASK;
123		frac = 1 << 6;
124	}
125
126	cpu_pll = ar934x_get_pll_freq(u_ar71xx_refclk, ref_div, nint,
127	    nfrac, frac, out_div);
128
129	pll = ATH_READ_REG(AR934X_SRIF_DDR_DPLL2_REG);
130	if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) {
131		out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) &
132		    AR934X_SRIF_DPLL2_OUTDIV_MASK;
133		pll = ATH_READ_REG(AR934X_SRIF_DDR_DPLL1_REG);
134		nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) &
135		    AR934X_SRIF_DPLL1_NINT_MASK;
136		nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK;
137		ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) &
138		    AR934X_SRIF_DPLL1_REFDIV_MASK;
139		frac = 1 << 18;
140	} else {
141		pll = ATH_READ_REG(AR934X_PLL_DDR_CONFIG_REG);
142		out_div = (pll >> AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT) &
143		    AR934X_PLL_DDR_CONFIG_OUTDIV_MASK;
144		ref_div = (pll >> AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) &
145		    AR934X_PLL_DDR_CONFIG_REFDIV_MASK;
146		nint = (pll >> AR934X_PLL_DDR_CONFIG_NINT_SHIFT) &
147		    AR934X_PLL_DDR_CONFIG_NINT_MASK;
148		nfrac = (pll >> AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT) &
149		    AR934X_PLL_DDR_CONFIG_NFRAC_MASK;
150		frac = 1 << 10;
151	}
152
153	ddr_pll = ar934x_get_pll_freq(u_ar71xx_refclk, ref_div, nint,
154	    nfrac, frac, out_div);
155
156	clk_ctrl = ATH_READ_REG(AR934X_PLL_CPU_DDR_CLK_CTRL_REG);
157
158	postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_SHIFT) &
159	    AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_MASK;
160
161	if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_PLL_BYPASS)
162	    u_ar71xx_cpu_freq = u_ar71xx_refclk;
163	else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPUCLK_FROM_CPUPLL)
164		u_ar71xx_cpu_freq = cpu_pll / (postdiv + 1);
165	else
166		u_ar71xx_cpu_freq = ddr_pll / (postdiv + 1);
167
168	postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_SHIFT) &
169	    AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_MASK;
170
171	if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_PLL_BYPASS)
172		u_ar71xx_ddr_freq = u_ar71xx_refclk;
173	else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDRCLK_FROM_DDRPLL)
174		u_ar71xx_ddr_freq = ddr_pll / (postdiv + 1);
175	else
176		u_ar71xx_ddr_freq = cpu_pll / (postdiv + 1);
177
178	postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_SHIFT) &
179		  AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_MASK;
180
181	if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_PLL_BYPASS)
182		u_ar71xx_ahb_freq = u_ar71xx_refclk;
183	else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL)
184		u_ar71xx_ahb_freq = ddr_pll / (postdiv + 1);
185	else
186		u_ar71xx_ahb_freq = cpu_pll / (postdiv + 1);
187
188	u_ar71xx_wdt_freq = u_ar71xx_refclk;
189	u_ar71xx_uart_freq = u_ar71xx_refclk;
190}
191
192static void
193ar934x_chip_device_stop(uint32_t mask)
194{
195	uint32_t reg;
196
197	reg = ATH_READ_REG(AR934X_RESET_REG_RESET_MODULE);
198	ATH_WRITE_REG(AR934X_RESET_REG_RESET_MODULE, reg | mask);
199}
200
201static void
202ar934x_chip_device_start(uint32_t mask)
203{
204	uint32_t reg;
205
206	reg = ATH_READ_REG(AR934X_RESET_REG_RESET_MODULE);
207	ATH_WRITE_REG(AR934X_RESET_REG_RESET_MODULE, reg & ~mask);
208}
209
210static int
211ar934x_chip_device_stopped(uint32_t mask)
212{
213	uint32_t reg;
214
215	reg = ATH_READ_REG(AR934X_RESET_REG_RESET_MODULE);
216	return ((reg & mask) == mask);
217}
218
219static void
220ar934x_chip_set_mii_speed(uint32_t unit, uint32_t speed)
221{
222
223	/* XXX TODO */
224	return;
225}
226
227/*
228 * XXX TODO !!
229 */
230static void
231ar934x_chip_set_pll_ge(int unit, int speed, uint32_t pll)
232{
233
234	switch (unit) {
235	case 0:
236		/* XXX TODO */
237		break;
238	case 1:
239		/* XXX TODO */
240		break;
241	default:
242		printf("%s: invalid PLL set for arge unit: %d\n",
243		    __func__, unit);
244		return;
245	}
246}
247
248static void
249ar934x_chip_ddr_flush_ge(int unit)
250{
251
252	switch (unit) {
253	case 0:
254		ar71xx_ddr_flush(AR934X_DDR_REG_FLUSH_GE0);
255		break;
256	case 1:
257		ar71xx_ddr_flush(AR934X_DDR_REG_FLUSH_GE1);
258		break;
259	default:
260		printf("%s: invalid DDR flush for arge unit: %d\n",
261		    __func__, unit);
262		return;
263	}
264}
265
266static void
267ar934x_chip_ddr_flush_ip2(void)
268{
269
270	ar71xx_ddr_flush(AR934X_DDR_REG_FLUSH_WMAC);
271}
272
273static uint32_t
274ar934x_chip_get_eth_pll(unsigned int mac, int speed)
275{
276#if 0
277	uint32_t pll;
278
279	switch (speed) {
280	case 10:
281		pll = AR933X_PLL_VAL_10;
282		break;
283	case 100:
284		pll = AR933X_PLL_VAL_100;
285		break;
286	case 1000:
287		pll = AR933X_PLL_VAL_1000;
288		break;
289	default:
290		printf("%s%d: invalid speed %d\n", __func__, mac, speed);
291		pll = 0;
292	}
293	return (pll);
294#endif
295	return (0);
296}
297
298static void
299ar934x_chip_init_usb_peripheral(void)
300{
301	uint32_t reg;
302
303	reg = ATH_READ_REG(AR934X_RESET_REG_BOOTSTRAP);
304	if (reg & AR934X_BOOTSTRAP_USB_MODE_DEVICE)
305		return;
306
307	ar71xx_device_stop(AR934X_RESET_USBSUS_OVERRIDE);
308	DELAY(100);
309
310	ar71xx_device_start(AR934X_RESET_USB_PHY);
311	DELAY(100);
312
313	ar71xx_device_start(AR934X_RESET_USB_PHY_ANALOG);
314	DELAY(100);
315
316	ar71xx_device_start(AR934X_RESET_USB_HOST);
317	DELAY(100);
318}
319
320struct ar71xx_cpu_def ar934x_chip_def = {
321	&ar934x_chip_detect_mem_size,
322	&ar934x_chip_detect_sys_frequency,
323	&ar934x_chip_device_stop,
324	&ar934x_chip_device_start,
325	&ar934x_chip_device_stopped,
326	&ar934x_chip_set_pll_ge,
327	&ar934x_chip_set_mii_speed,
328	&ar71xx_chip_set_mii_if,
329	&ar934x_chip_ddr_flush_ge,
330	&ar934x_chip_get_eth_pll,
331	&ar934x_chip_ddr_flush_ip2,
332	&ar934x_chip_init_usb_peripheral
333};
334