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;
95256491Sadrian	uint32_t reg;
96253511Sadrian
97253511Sadrian	bootstrap = ATH_READ_REG(AR934X_RESET_REG_BOOTSTRAP);
98253511Sadrian	if (bootstrap & AR934X_BOOTSTRAP_REF_CLK_40)
99253511Sadrian		u_ar71xx_refclk = 40 * 1000 * 1000;
100253511Sadrian	else
101253511Sadrian		u_ar71xx_refclk = 25 * 1000 * 1000;
102253511Sadrian
103253511Sadrian	pll = ATH_READ_REG(AR934X_SRIF_CPU_DPLL2_REG);
104253511Sadrian	if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) {
105253511Sadrian		out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) &
106253511Sadrian		    AR934X_SRIF_DPLL2_OUTDIV_MASK;
107253511Sadrian		pll = ATH_READ_REG(AR934X_SRIF_CPU_DPLL1_REG);
108253511Sadrian		nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) &
109253511Sadrian		    AR934X_SRIF_DPLL1_NINT_MASK;
110253511Sadrian		nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK;
111253511Sadrian		ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) &
112253511Sadrian		    AR934X_SRIF_DPLL1_REFDIV_MASK;
113253511Sadrian		frac = 1 << 18;
114253511Sadrian	} else {
115253511Sadrian		pll = ATH_READ_REG(AR934X_PLL_CPU_CONFIG_REG);
116253511Sadrian		out_div = (pll >> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
117253511Sadrian			AR934X_PLL_CPU_CONFIG_OUTDIV_MASK;
118253511Sadrian		ref_div = (pll >> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
119253511Sadrian			  AR934X_PLL_CPU_CONFIG_REFDIV_MASK;
120253511Sadrian		nint = (pll >> AR934X_PLL_CPU_CONFIG_NINT_SHIFT) &
121253511Sadrian		       AR934X_PLL_CPU_CONFIG_NINT_MASK;
122253511Sadrian		nfrac = (pll >> AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT) &
123253511Sadrian			AR934X_PLL_CPU_CONFIG_NFRAC_MASK;
124253511Sadrian		frac = 1 << 6;
125253511Sadrian	}
126253511Sadrian
127253511Sadrian	cpu_pll = ar934x_get_pll_freq(u_ar71xx_refclk, ref_div, nint,
128253511Sadrian	    nfrac, frac, out_div);
129253511Sadrian
130253511Sadrian	pll = ATH_READ_REG(AR934X_SRIF_DDR_DPLL2_REG);
131253511Sadrian	if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) {
132253511Sadrian		out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) &
133253511Sadrian		    AR934X_SRIF_DPLL2_OUTDIV_MASK;
134253511Sadrian		pll = ATH_READ_REG(AR934X_SRIF_DDR_DPLL1_REG);
135253511Sadrian		nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) &
136253511Sadrian		    AR934X_SRIF_DPLL1_NINT_MASK;
137253511Sadrian		nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK;
138253511Sadrian		ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) &
139253511Sadrian		    AR934X_SRIF_DPLL1_REFDIV_MASK;
140253511Sadrian		frac = 1 << 18;
141253511Sadrian	} else {
142253511Sadrian		pll = ATH_READ_REG(AR934X_PLL_DDR_CONFIG_REG);
143253511Sadrian		out_div = (pll >> AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT) &
144253511Sadrian		    AR934X_PLL_DDR_CONFIG_OUTDIV_MASK;
145253511Sadrian		ref_div = (pll >> AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) &
146253511Sadrian		    AR934X_PLL_DDR_CONFIG_REFDIV_MASK;
147253511Sadrian		nint = (pll >> AR934X_PLL_DDR_CONFIG_NINT_SHIFT) &
148253511Sadrian		    AR934X_PLL_DDR_CONFIG_NINT_MASK;
149253511Sadrian		nfrac = (pll >> AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT) &
150253511Sadrian		    AR934X_PLL_DDR_CONFIG_NFRAC_MASK;
151253511Sadrian		frac = 1 << 10;
152253511Sadrian	}
153253511Sadrian
154253511Sadrian	ddr_pll = ar934x_get_pll_freq(u_ar71xx_refclk, ref_div, nint,
155253511Sadrian	    nfrac, frac, out_div);
156253511Sadrian
157253511Sadrian	clk_ctrl = ATH_READ_REG(AR934X_PLL_CPU_DDR_CLK_CTRL_REG);
158253511Sadrian
159253511Sadrian	postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_SHIFT) &
160253511Sadrian	    AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_MASK;
161253511Sadrian
162253511Sadrian	if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_PLL_BYPASS)
163253511Sadrian	    u_ar71xx_cpu_freq = u_ar71xx_refclk;
164253511Sadrian	else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPUCLK_FROM_CPUPLL)
165253511Sadrian		u_ar71xx_cpu_freq = cpu_pll / (postdiv + 1);
166253511Sadrian	else
167253511Sadrian		u_ar71xx_cpu_freq = ddr_pll / (postdiv + 1);
168253511Sadrian
169253511Sadrian	postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_SHIFT) &
170253511Sadrian	    AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_MASK;
171253511Sadrian
172253511Sadrian	if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_PLL_BYPASS)
173253511Sadrian		u_ar71xx_ddr_freq = u_ar71xx_refclk;
174253511Sadrian	else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDRCLK_FROM_DDRPLL)
175253511Sadrian		u_ar71xx_ddr_freq = ddr_pll / (postdiv + 1);
176253511Sadrian	else
177253511Sadrian		u_ar71xx_ddr_freq = cpu_pll / (postdiv + 1);
178253511Sadrian
179253511Sadrian	postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_SHIFT) &
180253511Sadrian		  AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_MASK;
181253511Sadrian
182253511Sadrian	if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_PLL_BYPASS)
183253511Sadrian		u_ar71xx_ahb_freq = u_ar71xx_refclk;
184253511Sadrian	else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL)
185253511Sadrian		u_ar71xx_ahb_freq = ddr_pll / (postdiv + 1);
186253511Sadrian	else
187253511Sadrian		u_ar71xx_ahb_freq = cpu_pll / (postdiv + 1);
188253511Sadrian
189253511Sadrian	u_ar71xx_wdt_freq = u_ar71xx_refclk;
190253511Sadrian	u_ar71xx_uart_freq = u_ar71xx_refclk;
191256491Sadrian
192256491Sadrian	/*
193256491Sadrian	 * Next, fetch reference clock speed for MDIO bus.
194256491Sadrian	 */
195256491Sadrian	reg = ATH_READ_REG(AR934X_PLL_SWITCH_CLOCK_CONTROL_REG);
196256491Sadrian	if (reg & AR934X_PLL_SWITCH_CLOCK_CONTROL_MDIO_CLK_SEL) {
197256491Sadrian		printf("%s: mdio=100MHz\n", __func__);
198256491Sadrian		u_ar71xx_mdio_freq = (100 * 1000 * 1000);
199256491Sadrian	} else {
200256491Sadrian		printf("%s: mdio=%d Hz\n", __func__, u_ar71xx_refclk);
201256491Sadrian		u_ar71xx_mdio_freq = u_ar71xx_refclk;
202256491Sadrian	}
203253511Sadrian}
204253511Sadrian
205253511Sadrianstatic void
206253511Sadrianar934x_chip_device_stop(uint32_t mask)
207253511Sadrian{
208253511Sadrian	uint32_t reg;
209253511Sadrian
210253511Sadrian	reg = ATH_READ_REG(AR934X_RESET_REG_RESET_MODULE);
211253511Sadrian	ATH_WRITE_REG(AR934X_RESET_REG_RESET_MODULE, reg | mask);
212253511Sadrian}
213253511Sadrian
214253511Sadrianstatic void
215253511Sadrianar934x_chip_device_start(uint32_t mask)
216253511Sadrian{
217253511Sadrian	uint32_t reg;
218253511Sadrian
219253511Sadrian	reg = ATH_READ_REG(AR934X_RESET_REG_RESET_MODULE);
220253511Sadrian	ATH_WRITE_REG(AR934X_RESET_REG_RESET_MODULE, reg & ~mask);
221253511Sadrian}
222253511Sadrian
223253511Sadrianstatic int
224253511Sadrianar934x_chip_device_stopped(uint32_t mask)
225253511Sadrian{
226253511Sadrian	uint32_t reg;
227253511Sadrian
228253511Sadrian	reg = ATH_READ_REG(AR934X_RESET_REG_RESET_MODULE);
229253511Sadrian	return ((reg & mask) == mask);
230253511Sadrian}
231253511Sadrian
232253511Sadrianstatic void
233253511Sadrianar934x_chip_set_mii_speed(uint32_t unit, uint32_t speed)
234253511Sadrian{
235253511Sadrian
236253511Sadrian	/* XXX TODO */
237253511Sadrian	return;
238253511Sadrian}
239253511Sadrian
240253511Sadrian/*
241253511Sadrian * XXX TODO !!
242253511Sadrian */
243253511Sadrianstatic void
244253511Sadrianar934x_chip_set_pll_ge(int unit, int speed, uint32_t pll)
245253511Sadrian{
246253511Sadrian
247253511Sadrian	switch (unit) {
248253511Sadrian	case 0:
249256491Sadrian		ATH_WRITE_REG(AR934X_PLL_ETH_XMII_CONTROL_REG, pll);
250253511Sadrian		break;
251253511Sadrian	case 1:
252256491Sadrian		/* XXX nothing */
253253511Sadrian		break;
254253511Sadrian	default:
255253511Sadrian		printf("%s: invalid PLL set for arge unit: %d\n",
256253511Sadrian		    __func__, unit);
257253511Sadrian		return;
258253511Sadrian	}
259253511Sadrian}
260253511Sadrian
261253511Sadrianstatic void
262285121Sadrianar934x_chip_ddr_flush(ar71xx_flush_ddr_id_t id)
263253511Sadrian{
264253511Sadrian
265285121Sadrian	switch (id) {
266285121Sadrian	case AR71XX_CPU_DDR_FLUSH_GE0:
267253511Sadrian		ar71xx_ddr_flush(AR934X_DDR_REG_FLUSH_GE0);
268253511Sadrian		break;
269285121Sadrian	case AR71XX_CPU_DDR_FLUSH_GE1:
270253511Sadrian		ar71xx_ddr_flush(AR934X_DDR_REG_FLUSH_GE1);
271253511Sadrian		break;
272285121Sadrian	case AR71XX_CPU_DDR_FLUSH_USB:
273285121Sadrian		ar71xx_ddr_flush(AR934X_DDR_REG_FLUSH_USB);
274285121Sadrian		break;
275285121Sadrian	case AR71XX_CPU_DDR_FLUSH_PCIE:
276285121Sadrian		ar71xx_ddr_flush(AR934X_DDR_REG_FLUSH_PCIE);
277285121Sadrian		break;
278285121Sadrian	case AR71XX_CPU_DDR_FLUSH_WMAC:
279285121Sadrian		ar71xx_ddr_flush(AR934X_DDR_REG_FLUSH_WMAC);
280285121Sadrian		break;
281253511Sadrian	default:
282285121Sadrian		printf("%s: invalid DDR flush id (%d)\n", __func__, id);
283285121Sadrian		break;
284253511Sadrian	}
285253511Sadrian}
286253511Sadrian
287253511Sadrian
288253511Sadrianstatic uint32_t
289253511Sadrianar934x_chip_get_eth_pll(unsigned int mac, int speed)
290253511Sadrian{
291253511Sadrian	uint32_t pll;
292253511Sadrian
293253511Sadrian	switch (speed) {
294253511Sadrian	case 10:
295256491Sadrian		pll = AR934X_PLL_VAL_10;
296253511Sadrian		break;
297253511Sadrian	case 100:
298256491Sadrian		pll = AR934X_PLL_VAL_100;
299253511Sadrian		break;
300253511Sadrian	case 1000:
301256491Sadrian		pll = AR934X_PLL_VAL_1000;
302253511Sadrian		break;
303253511Sadrian	default:
304253511Sadrian		printf("%s%d: invalid speed %d\n", __func__, mac, speed);
305253511Sadrian		pll = 0;
306253511Sadrian	}
307253511Sadrian	return (pll);
308253511Sadrian}
309253511Sadrian
310253511Sadrianstatic void
311256491Sadrianar934x_chip_reset_ethernet_switch(void)
312256491Sadrian{
313256491Sadrian
314256491Sadrian	ar71xx_device_stop(AR934X_RESET_ETH_SWITCH);
315256491Sadrian	DELAY(100);
316256491Sadrian	ar71xx_device_start(AR934X_RESET_ETH_SWITCH);
317256491Sadrian	DELAY(100);
318256491Sadrian}
319256491Sadrian
320256491Sadrianstatic void
321256491Sadrianar934x_configure_gmac(uint32_t gmac_cfg)
322256491Sadrian{
323256491Sadrian	uint32_t reg;
324256491Sadrian
325256491Sadrian	reg = ATH_READ_REG(AR934X_GMAC_REG_ETH_CFG);
326256491Sadrian	printf("%s: ETH_CFG=0x%08x\n", __func__, reg);
327256491Sadrian
328256491Sadrian	reg &= ~(AR934X_ETH_CFG_RGMII_GMAC0 | AR934X_ETH_CFG_MII_GMAC0 |
329256491Sadrian	    AR934X_ETH_CFG_MII_GMAC0 | AR934X_ETH_CFG_SW_ONLY_MODE |
330256491Sadrian	    AR934X_ETH_CFG_SW_PHY_SWAP);
331256491Sadrian
332256491Sadrian	reg |= gmac_cfg;
333256491Sadrian
334256491Sadrian	ATH_WRITE_REG(AR934X_GMAC_REG_ETH_CFG, reg);
335256491Sadrian}
336256491Sadrian
337256491Sadrianstatic void
338253511Sadrianar934x_chip_init_usb_peripheral(void)
339253511Sadrian{
340253511Sadrian	uint32_t reg;
341253511Sadrian
342253511Sadrian	reg = ATH_READ_REG(AR934X_RESET_REG_BOOTSTRAP);
343253511Sadrian	if (reg & AR934X_BOOTSTRAP_USB_MODE_DEVICE)
344253511Sadrian		return;
345253511Sadrian
346253511Sadrian	ar71xx_device_stop(AR934X_RESET_USBSUS_OVERRIDE);
347253511Sadrian	DELAY(100);
348253511Sadrian
349253511Sadrian	ar71xx_device_start(AR934X_RESET_USB_PHY);
350253511Sadrian	DELAY(100);
351253511Sadrian
352253511Sadrian	ar71xx_device_start(AR934X_RESET_USB_PHY_ANALOG);
353253511Sadrian	DELAY(100);
354253511Sadrian
355253511Sadrian	ar71xx_device_start(AR934X_RESET_USB_HOST);
356253511Sadrian	DELAY(100);
357253511Sadrian}
358253511Sadrian
359256491Sadrianstatic void
360256491Sadrianar934x_chip_set_mii_if(uint32_t unit, uint32_t mii_mode)
361256491Sadrian{
362256491Sadrian
363256491Sadrian	/*
364256491Sadrian	 * XXX !
365256491Sadrian	 *
366256491Sadrian	 * Nothing to see here; although gmac0 can have its
367256491Sadrian	 * MII configuration changed, the register values
368256491Sadrian	 * are slightly different.
369256491Sadrian	 */
370256491Sadrian}
371256491Sadrian
372256491Sadrian/*
373256491Sadrian * XXX TODO: fetch default MII divider configuration
374256491Sadrian */
375256491Sadrian
376256491Sadrianstatic void
377256491Sadrianar934x_chip_reset_wmac(void)
378256491Sadrian{
379256491Sadrian
380263296Sadrian	/* XXX TODO */
381256491Sadrian}
382256491Sadrian
383256491Sadrianstatic void
384256491Sadrianar934x_chip_init_gmac(void)
385256491Sadrian{
386256491Sadrian	long gmac_cfg;
387256491Sadrian
388256491Sadrian	if (resource_long_value("ar934x_gmac", 0, "gmac_cfg",
389256491Sadrian	    &gmac_cfg) == 0) {
390256491Sadrian		printf("%s: gmac_cfg=0x%08lx\n",
391256491Sadrian		    __func__,
392256491Sadrian		    (long) gmac_cfg);
393256491Sadrian		ar934x_configure_gmac((uint32_t) gmac_cfg);
394256491Sadrian	}
395256491Sadrian}
396256491Sadrian
397263296Sadrian/*
398263296Sadrian * Reset the NAND Flash Controller.
399263296Sadrian *
400263296Sadrian * + active=1 means "make it active".
401263296Sadrian * + active=0 means "make it inactive".
402263296Sadrian */
403263296Sadrianstatic void
404263296Sadrianar934x_chip_reset_nfc(int active)
405263296Sadrian{
406263296Sadrian
407263296Sadrian	if (active) {
408263296Sadrian		ar71xx_device_start(AR934X_RESET_NANDF);
409263296Sadrian		DELAY(100);
410263296Sadrian
411263296Sadrian		ar71xx_device_start(AR934X_RESET_ETH_SWITCH_ANALOG);
412263296Sadrian		DELAY(250);
413263296Sadrian	} else {
414263296Sadrian		ar71xx_device_stop(AR934X_RESET_ETH_SWITCH_ANALOG);
415263296Sadrian		DELAY(250);
416263296Sadrian
417263296Sadrian		ar71xx_device_stop(AR934X_RESET_NANDF);
418263296Sadrian		DELAY(100);
419263296Sadrian	}
420263296Sadrian}
421263296Sadrian
422276610Sadrian/*
423276610Sadrian * Configure the GPIO output mux setup.
424276610Sadrian *
425276610Sadrian * The AR934x introduced an output mux which allowed
426276610Sadrian * certain functions to be configured on any pin.
427276610Sadrian * Specifically, the switch PHY link LEDs and
428276610Sadrian * WMAC external RX LNA switches are not limited to
429276610Sadrian * a specific GPIO pin.
430276610Sadrian */
431276610Sadrianstatic void
432276610Sadrianar934x_chip_gpio_output_configure(int gpio, uint8_t func)
433276610Sadrian{
434276610Sadrian	uint32_t reg, s;
435276610Sadrian	uint32_t t;
436276610Sadrian
437276610Sadrian	if (gpio > AR934X_GPIO_COUNT)
438276610Sadrian		return;
439276610Sadrian
440298848Spfg	reg = AR934X_GPIO_REG_OUT_FUNC0 + rounddown(gpio, 4);
441276610Sadrian	s = 8 * (gpio % 4);
442276610Sadrian
443276610Sadrian	/* read-modify-write */
444276610Sadrian	t = ATH_READ_REG(AR71XX_GPIO_BASE + reg);
445276610Sadrian	t &= ~(0xff << s);
446276610Sadrian	t |= func << s;
447276610Sadrian	ATH_WRITE_REG(AR71XX_GPIO_BASE + reg, t);
448276610Sadrian
449276610Sadrian	/* flush write */
450276610Sadrian	ATH_READ_REG(AR71XX_GPIO_BASE + reg);
451276610Sadrian}
452276610Sadrian
453253511Sadrianstruct ar71xx_cpu_def ar934x_chip_def = {
454253511Sadrian	&ar934x_chip_detect_mem_size,
455253511Sadrian	&ar934x_chip_detect_sys_frequency,
456253511Sadrian	&ar934x_chip_device_stop,
457253511Sadrian	&ar934x_chip_device_start,
458253511Sadrian	&ar934x_chip_device_stopped,
459253511Sadrian	&ar934x_chip_set_pll_ge,
460253511Sadrian	&ar934x_chip_set_mii_speed,
461256491Sadrian	&ar934x_chip_set_mii_if,
462253511Sadrian	&ar934x_chip_get_eth_pll,
463285121Sadrian	&ar934x_chip_ddr_flush,
464256491Sadrian	&ar934x_chip_init_usb_peripheral,
465256491Sadrian	&ar934x_chip_reset_ethernet_switch,
466256491Sadrian	&ar934x_chip_reset_wmac,
467256491Sadrian	&ar934x_chip_init_gmac,
468263296Sadrian	&ar934x_chip_reset_nfc,
469276610Sadrian	&ar934x_chip_gpio_output_configure,
470253511Sadrian};
471