1253511Sadrian/*-
2253511Sadrian * Copyright (c) 2013 Adrian Chadd <adrian@FreeBSD.org>
3253511Sadrian * All rights reserved.
4253511Sadrian *
5253511Sadrian * Redistribution and use in source and binary forms, with or without
6253511Sadrian * modification, are permitted provided that the following conditions
7253511Sadrian * are met:
8253511Sadrian * 1. Redistributions of source code must retain the above copyright
9253511Sadrian *    notice, this list of conditions and the following disclaimer.
10253511Sadrian * 2. Redistributions in binary form must reproduce the above copyright
11253511Sadrian *    notice, this list of conditions and the following disclaimer in the
12253511Sadrian *    documentation and/or other materials provided with the distribution.
13253511Sadrian *
14253511Sadrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15253511Sadrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16253511Sadrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17253511Sadrian * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18253511Sadrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19253511Sadrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20253511Sadrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21253511Sadrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22253511Sadrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23253511Sadrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24253511Sadrian * SUCH DAMAGE.
25253511Sadrian */
26253511Sadrian
27253511Sadrian#include <sys/cdefs.h>
28253511Sadrian__FBSDID("$FreeBSD$");
29253511Sadrian
30253511Sadrian#include "opt_ddb.h"
31253511Sadrian
32253511Sadrian#include <sys/param.h>
33253511Sadrian#include <sys/conf.h>
34253511Sadrian#include <sys/kernel.h>
35253511Sadrian#include <sys/systm.h>
36253511Sadrian#include <sys/bus.h>
37253511Sadrian#include <sys/cons.h>
38253511Sadrian#include <sys/kdb.h>
39253511Sadrian#include <sys/reboot.h>
40253511Sadrian
41253511Sadrian#include <vm/vm.h>
42253511Sadrian#include <vm/vm_page.h>
43253511Sadrian
44253511Sadrian#include <net/ethernet.h>
45253511Sadrian
46253511Sadrian#include <machine/clock.h>
47253511Sadrian#include <machine/cpu.h>
48253511Sadrian#include <machine/cpuregs.h>
49253511Sadrian#include <machine/hwfunc.h>
50253511Sadrian#include <machine/md_var.h>
51253511Sadrian#include <machine/trap.h>
52253511Sadrian#include <machine/vmparam.h>
53253511Sadrian
54253511Sadrian#include <mips/atheros/ar71xxreg.h>
55253511Sadrian#include <mips/atheros/ar934xreg.h>
56253511Sadrian
57253511Sadrian#include <mips/atheros/ar71xx_cpudef.h>
58253511Sadrian#include <mips/atheros/ar71xx_setup.h>
59253511Sadrian
60253511Sadrian#include <mips/atheros/ar71xx_chip.h>
61253511Sadrian#include <mips/atheros/ar934x_chip.h>
62253511Sadrian
63253511Sadrianstatic void
64253511Sadrianar934x_chip_detect_mem_size(void)
65253511Sadrian{
66253511Sadrian}
67253511Sadrian
68253511Sadrianstatic uint32_t
69253511Sadrianar934x_get_pll_freq(uint32_t ref, uint32_t ref_div, uint32_t nint,
70253511Sadrian    uint32_t nfrac, uint32_t frac, uint32_t out_div)
71253511Sadrian{
72253511Sadrian	uint64_t t;
73253511Sadrian	uint32_t ret;
74253511Sadrian
75253511Sadrian	t = u_ar71xx_refclk;
76253511Sadrian	t *= nint;
77253511Sadrian	t = t / ref_div;
78253511Sadrian	ret = t;
79253511Sadrian
80253511Sadrian	t = u_ar71xx_refclk;
81253511Sadrian	t *= nfrac;
82253511Sadrian	t = t / (ref_div * frac);
83253511Sadrian	ret += t;
84253511Sadrian
85253511Sadrian	ret /= (1 << out_div);
86253511Sadrian	return (ret);
87253511Sadrian}
88253511Sadrian
89253511Sadrianstatic void
90253511Sadrianar934x_chip_detect_sys_frequency(void)
91253511Sadrian{
92253511Sadrian	uint32_t pll, out_div, ref_div, nint, nfrac, frac, clk_ctrl, postdiv;
93253511Sadrian	uint32_t cpu_pll, ddr_pll;
94253511Sadrian	uint32_t bootstrap;
95253511Sadrian
96253511Sadrian	bootstrap = ATH_READ_REG(AR934X_RESET_REG_BOOTSTRAP);
97253511Sadrian	if (bootstrap & AR934X_BOOTSTRAP_REF_CLK_40)
98253511Sadrian		u_ar71xx_refclk = 40 * 1000 * 1000;
99253511Sadrian	else
100253511Sadrian		u_ar71xx_refclk = 25 * 1000 * 1000;
101253511Sadrian
102253511Sadrian	pll = ATH_READ_REG(AR934X_SRIF_CPU_DPLL2_REG);
103253511Sadrian	if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) {
104253511Sadrian		out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) &
105253511Sadrian		    AR934X_SRIF_DPLL2_OUTDIV_MASK;
106253511Sadrian		pll = ATH_READ_REG(AR934X_SRIF_CPU_DPLL1_REG);
107253511Sadrian		nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) &
108253511Sadrian		    AR934X_SRIF_DPLL1_NINT_MASK;
109253511Sadrian		nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK;
110253511Sadrian		ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) &
111253511Sadrian		    AR934X_SRIF_DPLL1_REFDIV_MASK;
112253511Sadrian		frac = 1 << 18;
113253511Sadrian	} else {
114253511Sadrian		pll = ATH_READ_REG(AR934X_PLL_CPU_CONFIG_REG);
115253511Sadrian		out_div = (pll >> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
116253511Sadrian			AR934X_PLL_CPU_CONFIG_OUTDIV_MASK;
117253511Sadrian		ref_div = (pll >> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
118253511Sadrian			  AR934X_PLL_CPU_CONFIG_REFDIV_MASK;
119253511Sadrian		nint = (pll >> AR934X_PLL_CPU_CONFIG_NINT_SHIFT) &
120253511Sadrian		       AR934X_PLL_CPU_CONFIG_NINT_MASK;
121253511Sadrian		nfrac = (pll >> AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT) &
122253511Sadrian			AR934X_PLL_CPU_CONFIG_NFRAC_MASK;
123253511Sadrian		frac = 1 << 6;
124253511Sadrian	}
125253511Sadrian
126253511Sadrian	cpu_pll = ar934x_get_pll_freq(u_ar71xx_refclk, ref_div, nint,
127253511Sadrian	    nfrac, frac, out_div);
128253511Sadrian
129253511Sadrian	pll = ATH_READ_REG(AR934X_SRIF_DDR_DPLL2_REG);
130253511Sadrian	if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) {
131253511Sadrian		out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) &
132253511Sadrian		    AR934X_SRIF_DPLL2_OUTDIV_MASK;
133253511Sadrian		pll = ATH_READ_REG(AR934X_SRIF_DDR_DPLL1_REG);
134253511Sadrian		nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) &
135253511Sadrian		    AR934X_SRIF_DPLL1_NINT_MASK;
136253511Sadrian		nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK;
137253511Sadrian		ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) &
138253511Sadrian		    AR934X_SRIF_DPLL1_REFDIV_MASK;
139253511Sadrian		frac = 1 << 18;
140253511Sadrian	} else {
141253511Sadrian		pll = ATH_READ_REG(AR934X_PLL_DDR_CONFIG_REG);
142253511Sadrian		out_div = (pll >> AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT) &
143253511Sadrian		    AR934X_PLL_DDR_CONFIG_OUTDIV_MASK;
144253511Sadrian		ref_div = (pll >> AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) &
145253511Sadrian		    AR934X_PLL_DDR_CONFIG_REFDIV_MASK;
146253511Sadrian		nint = (pll >> AR934X_PLL_DDR_CONFIG_NINT_SHIFT) &
147253511Sadrian		    AR934X_PLL_DDR_CONFIG_NINT_MASK;
148253511Sadrian		nfrac = (pll >> AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT) &
149253511Sadrian		    AR934X_PLL_DDR_CONFIG_NFRAC_MASK;
150253511Sadrian		frac = 1 << 10;
151253511Sadrian	}
152253511Sadrian
153253511Sadrian	ddr_pll = ar934x_get_pll_freq(u_ar71xx_refclk, ref_div, nint,
154253511Sadrian	    nfrac, frac, out_div);
155253511Sadrian
156253511Sadrian	clk_ctrl = ATH_READ_REG(AR934X_PLL_CPU_DDR_CLK_CTRL_REG);
157253511Sadrian
158253511Sadrian	postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_SHIFT) &
159253511Sadrian	    AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_MASK;
160253511Sadrian
161253511Sadrian	if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_PLL_BYPASS)
162253511Sadrian	    u_ar71xx_cpu_freq = u_ar71xx_refclk;
163253511Sadrian	else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPUCLK_FROM_CPUPLL)
164253511Sadrian		u_ar71xx_cpu_freq = cpu_pll / (postdiv + 1);
165253511Sadrian	else
166253511Sadrian		u_ar71xx_cpu_freq = ddr_pll / (postdiv + 1);
167253511Sadrian
168253511Sadrian	postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_SHIFT) &
169253511Sadrian	    AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_MASK;
170253511Sadrian
171253511Sadrian	if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_PLL_BYPASS)
172253511Sadrian		u_ar71xx_ddr_freq = u_ar71xx_refclk;
173253511Sadrian	else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDRCLK_FROM_DDRPLL)
174253511Sadrian		u_ar71xx_ddr_freq = ddr_pll / (postdiv + 1);
175253511Sadrian	else
176253511Sadrian		u_ar71xx_ddr_freq = cpu_pll / (postdiv + 1);
177253511Sadrian
178253511Sadrian	postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_SHIFT) &
179253511Sadrian		  AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_MASK;
180253511Sadrian
181253511Sadrian	if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_PLL_BYPASS)
182253511Sadrian		u_ar71xx_ahb_freq = u_ar71xx_refclk;
183253511Sadrian	else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL)
184253511Sadrian		u_ar71xx_ahb_freq = ddr_pll / (postdiv + 1);
185253511Sadrian	else
186253511Sadrian		u_ar71xx_ahb_freq = cpu_pll / (postdiv + 1);
187253511Sadrian
188253511Sadrian	u_ar71xx_wdt_freq = u_ar71xx_refclk;
189253511Sadrian	u_ar71xx_uart_freq = u_ar71xx_refclk;
190253511Sadrian}
191253511Sadrian
192253511Sadrianstatic void
193253511Sadrianar934x_chip_device_stop(uint32_t mask)
194253511Sadrian{
195253511Sadrian	uint32_t reg;
196253511Sadrian
197253511Sadrian	reg = ATH_READ_REG(AR934X_RESET_REG_RESET_MODULE);
198253511Sadrian	ATH_WRITE_REG(AR934X_RESET_REG_RESET_MODULE, reg | mask);
199253511Sadrian}
200253511Sadrian
201253511Sadrianstatic void
202253511Sadrianar934x_chip_device_start(uint32_t mask)
203253511Sadrian{
204253511Sadrian	uint32_t reg;
205253511Sadrian
206253511Sadrian	reg = ATH_READ_REG(AR934X_RESET_REG_RESET_MODULE);
207253511Sadrian	ATH_WRITE_REG(AR934X_RESET_REG_RESET_MODULE, reg & ~mask);
208253511Sadrian}
209253511Sadrian
210253511Sadrianstatic int
211253511Sadrianar934x_chip_device_stopped(uint32_t mask)
212253511Sadrian{
213253511Sadrian	uint32_t reg;
214253511Sadrian
215253511Sadrian	reg = ATH_READ_REG(AR934X_RESET_REG_RESET_MODULE);
216253511Sadrian	return ((reg & mask) == mask);
217253511Sadrian}
218253511Sadrian
219253511Sadrianstatic void
220253511Sadrianar934x_chip_set_mii_speed(uint32_t unit, uint32_t speed)
221253511Sadrian{
222253511Sadrian
223253511Sadrian	/* XXX TODO */
224253511Sadrian	return;
225253511Sadrian}
226253511Sadrian
227253511Sadrian/*
228253511Sadrian * XXX TODO !!
229253511Sadrian */
230253511Sadrianstatic void
231253511Sadrianar934x_chip_set_pll_ge(int unit, int speed, uint32_t pll)
232253511Sadrian{
233253511Sadrian
234253511Sadrian	switch (unit) {
235253511Sadrian	case 0:
236253511Sadrian		/* XXX TODO */
237253511Sadrian		break;
238253511Sadrian	case 1:
239253511Sadrian		/* XXX TODO */
240253511Sadrian		break;
241253511Sadrian	default:
242253511Sadrian		printf("%s: invalid PLL set for arge unit: %d\n",
243253511Sadrian		    __func__, unit);
244253511Sadrian		return;
245253511Sadrian	}
246253511Sadrian}
247253511Sadrian
248253511Sadrianstatic void
249253511Sadrianar934x_chip_ddr_flush_ge(int unit)
250253511Sadrian{
251253511Sadrian
252253511Sadrian	switch (unit) {
253253511Sadrian	case 0:
254253511Sadrian		ar71xx_ddr_flush(AR934X_DDR_REG_FLUSH_GE0);
255253511Sadrian		break;
256253511Sadrian	case 1:
257253511Sadrian		ar71xx_ddr_flush(AR934X_DDR_REG_FLUSH_GE1);
258253511Sadrian		break;
259253511Sadrian	default:
260253511Sadrian		printf("%s: invalid DDR flush for arge unit: %d\n",
261253511Sadrian		    __func__, unit);
262253511Sadrian		return;
263253511Sadrian	}
264253511Sadrian}
265253511Sadrian
266253511Sadrianstatic void
267253511Sadrianar934x_chip_ddr_flush_ip2(void)
268253511Sadrian{
269253511Sadrian
270253511Sadrian	ar71xx_ddr_flush(AR934X_DDR_REG_FLUSH_WMAC);
271253511Sadrian}
272253511Sadrian
273253511Sadrianstatic uint32_t
274253511Sadrianar934x_chip_get_eth_pll(unsigned int mac, int speed)
275253511Sadrian{
276253511Sadrian#if 0
277253511Sadrian	uint32_t pll;
278253511Sadrian
279253511Sadrian	switch (speed) {
280253511Sadrian	case 10:
281253511Sadrian		pll = AR933X_PLL_VAL_10;
282253511Sadrian		break;
283253511Sadrian	case 100:
284253511Sadrian		pll = AR933X_PLL_VAL_100;
285253511Sadrian		break;
286253511Sadrian	case 1000:
287253511Sadrian		pll = AR933X_PLL_VAL_1000;
288253511Sadrian		break;
289253511Sadrian	default:
290253511Sadrian		printf("%s%d: invalid speed %d\n", __func__, mac, speed);
291253511Sadrian		pll = 0;
292253511Sadrian	}
293253511Sadrian	return (pll);
294253511Sadrian#endif
295253511Sadrian	return (0);
296253511Sadrian}
297253511Sadrian
298253511Sadrianstatic void
299253511Sadrianar934x_chip_init_usb_peripheral(void)
300253511Sadrian{
301253511Sadrian	uint32_t reg;
302253511Sadrian
303253511Sadrian	reg = ATH_READ_REG(AR934X_RESET_REG_BOOTSTRAP);
304253511Sadrian	if (reg & AR934X_BOOTSTRAP_USB_MODE_DEVICE)
305253511Sadrian		return;
306253511Sadrian
307253511Sadrian	ar71xx_device_stop(AR934X_RESET_USBSUS_OVERRIDE);
308253511Sadrian	DELAY(100);
309253511Sadrian
310253511Sadrian	ar71xx_device_start(AR934X_RESET_USB_PHY);
311253511Sadrian	DELAY(100);
312253511Sadrian
313253511Sadrian	ar71xx_device_start(AR934X_RESET_USB_PHY_ANALOG);
314253511Sadrian	DELAY(100);
315253511Sadrian
316253511Sadrian	ar71xx_device_start(AR934X_RESET_USB_HOST);
317253511Sadrian	DELAY(100);
318253511Sadrian}
319253511Sadrian
320253511Sadrianstruct ar71xx_cpu_def ar934x_chip_def = {
321253511Sadrian	&ar934x_chip_detect_mem_size,
322253511Sadrian	&ar934x_chip_detect_sys_frequency,
323253511Sadrian	&ar934x_chip_device_stop,
324253511Sadrian	&ar934x_chip_device_start,
325253511Sadrian	&ar934x_chip_device_stopped,
326253511Sadrian	&ar934x_chip_set_pll_ge,
327253511Sadrian	&ar934x_chip_set_mii_speed,
328253511Sadrian	&ar71xx_chip_set_mii_if,
329253511Sadrian	&ar934x_chip_ddr_flush_ge,
330253511Sadrian	&ar934x_chip_get_eth_pll,
331253511Sadrian	&ar934x_chip_ddr_flush_ip2,
332253511Sadrian	&ar934x_chip_init_usb_peripheral
333253511Sadrian};
334