1211498Sadrian/*-
2211498Sadrian * Copyright (c) 2010 Adrian Chadd
3211498Sadrian * All rights reserved.
4211498Sadrian *
5211498Sadrian * Redistribution and use in source and binary forms, with or without
6211498Sadrian * modification, are permitted provided that the following conditions
7211498Sadrian * are met:
8211498Sadrian * 1. Redistributions of source code must retain the above copyright
9211498Sadrian *    notice, this list of conditions and the following disclaimer.
10211498Sadrian * 2. Redistributions in binary form must reproduce the above copyright
11211498Sadrian *    notice, this list of conditions and the following disclaimer in the
12211498Sadrian *    documentation and/or other materials provided with the distribution.
13211498Sadrian *
14211498Sadrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15211498Sadrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16211498Sadrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17211498Sadrian * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18211498Sadrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19211498Sadrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20211498Sadrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21211498Sadrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22211498Sadrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23211498Sadrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24211498Sadrian * SUCH DAMAGE.
25211498Sadrian */
26211498Sadrian
27211476Sadrian#include <sys/cdefs.h>
28211476Sadrian__FBSDID("$FreeBSD$");
29211476Sadrian
30211476Sadrian#include "opt_ddb.h"
31211476Sadrian
32211476Sadrian#include <sys/param.h>
33211476Sadrian#include <sys/conf.h>
34211476Sadrian#include <sys/kernel.h>
35211476Sadrian#include <sys/systm.h>
36211476Sadrian#include <sys/bus.h>
37211476Sadrian#include <sys/cons.h>
38211476Sadrian#include <sys/kdb.h>
39211476Sadrian#include <sys/reboot.h>
40228450Sadrian
41211476Sadrian#include <vm/vm.h>
42211476Sadrian#include <vm/vm_page.h>
43228450Sadrian
44211476Sadrian#include <net/ethernet.h>
45228450Sadrian
46211476Sadrian#include <machine/clock.h>
47211476Sadrian#include <machine/cpu.h>
48223562Skevlo#include <machine/cpuregs.h>
49211476Sadrian#include <machine/hwfunc.h>
50211476Sadrian#include <machine/md_var.h>
51211476Sadrian#include <machine/trap.h>
52211476Sadrian#include <machine/vmparam.h>
53228450Sadrian
54211476Sadrian#include <mips/atheros/ar71xxreg.h>
55211476Sadrian#include <mips/atheros/ar71xx_chip.h>
56211476Sadrian#include <mips/atheros/ar71xx_cpudef.h>
57211476Sadrian
58223562Skevlo#include <mips/sentry5/s5reg.h>
59223562Skevlo
60211476Sadrian/* XXX these should replace the current definitions in ar71xxreg.h */
61211476Sadrian/* XXX perhaps an ar71xx_chip.h header file? */
62211476Sadrian#define AR71XX_PLL_REG_CPU_CONFIG       AR71XX_PLL_CPU_BASE + 0x00
63211476Sadrian#define AR71XX_PLL_REG_SEC_CONFIG       AR71XX_PLL_CPU_BASE + 0x04
64211476Sadrian#define AR71XX_PLL_REG_ETH0_INT_CLOCK   AR71XX_PLL_CPU_BASE + 0x10
65211476Sadrian#define AR71XX_PLL_REG_ETH1_INT_CLOCK   AR71XX_PLL_CPU_BASE + 0x14
66211476Sadrian
67211476Sadrian#define AR71XX_PLL_DIV_SHIFT            3
68211476Sadrian#define AR71XX_PLL_DIV_MASK             0x1f
69211476Sadrian#define AR71XX_CPU_DIV_SHIFT            16
70211476Sadrian#define AR71XX_CPU_DIV_MASK             0x3
71211476Sadrian#define AR71XX_DDR_DIV_SHIFT            18
72211476Sadrian#define AR71XX_DDR_DIV_MASK             0x3
73211476Sadrian#define AR71XX_AHB_DIV_SHIFT            20
74211476Sadrian#define AR71XX_AHB_DIV_MASK             0x7
75211476Sadrian
76211476Sadrian/* XXX these shouldn't be in here - this file is a per-chip file */
77211476Sadrian/* XXX these should be in the top-level ar71xx type, not ar71xx -chip */
78211476Sadrianuint32_t u_ar71xx_cpu_freq;
79211476Sadrianuint32_t u_ar71xx_ahb_freq;
80211476Sadrianuint32_t u_ar71xx_ddr_freq;
81253508Sadrianuint32_t u_ar71xx_uart_freq;
82253508Sadrianuint32_t u_ar71xx_wdt_freq;
83248781Sadrianuint32_t u_ar71xx_refclk;
84211476Sadrian
85211476Sadrianstatic void
86211476Sadrianar71xx_chip_detect_mem_size(void)
87211476Sadrian{
88211476Sadrian}
89211476Sadrian
90211476Sadrianstatic void
91211476Sadrianar71xx_chip_detect_sys_frequency(void)
92211476Sadrian{
93211476Sadrian	uint32_t pll;
94211476Sadrian	uint32_t freq;
95211476Sadrian	uint32_t div;
96211476Sadrian
97248781Sadrian	u_ar71xx_refclk = AR71XX_BASE_FREQ;
98248781Sadrian
99211476Sadrian	pll = ATH_READ_REG(AR71XX_PLL_REG_CPU_CONFIG);
100211476Sadrian
101211476Sadrian	div = ((pll >> AR71XX_PLL_DIV_SHIFT) & AR71XX_PLL_DIV_MASK) + 1;
102211476Sadrian	freq = div * AR71XX_BASE_FREQ;
103211476Sadrian
104211476Sadrian	div = ((pll >> AR71XX_CPU_DIV_SHIFT) & AR71XX_CPU_DIV_MASK) + 1;
105211476Sadrian	u_ar71xx_cpu_freq = freq / div;
106211476Sadrian
107211476Sadrian	div = ((pll >> AR71XX_DDR_DIV_SHIFT) & AR71XX_DDR_DIV_MASK) + 1;
108211476Sadrian	u_ar71xx_ddr_freq = freq / div;
109211476Sadrian
110211476Sadrian	div = (((pll >> AR71XX_AHB_DIV_SHIFT) & AR71XX_AHB_DIV_MASK) + 1) * 2;
111211476Sadrian	u_ar71xx_ahb_freq = u_ar71xx_cpu_freq / div;
112253508Sadrian	u_ar71xx_wdt_freq = u_ar71xx_cpu_freq / div;
113253508Sadrian	u_ar71xx_uart_freq = u_ar71xx_cpu_freq / div;
114211476Sadrian}
115211476Sadrian
116211476Sadrian/*
117211476Sadrian * This does not lock the CPU whilst doing the work!
118211476Sadrian */
119211476Sadrianstatic void
120211476Sadrianar71xx_chip_device_stop(uint32_t mask)
121211476Sadrian{
122211476Sadrian	uint32_t reg;
123211476Sadrian
124211476Sadrian	reg = ATH_READ_REG(AR71XX_RST_RESET);
125211476Sadrian	ATH_WRITE_REG(AR71XX_RST_RESET, reg | mask);
126211476Sadrian}
127211476Sadrian
128211476Sadrianstatic void
129211476Sadrianar71xx_chip_device_start(uint32_t mask)
130211476Sadrian{
131211476Sadrian	uint32_t reg;
132211476Sadrian
133211476Sadrian	reg = ATH_READ_REG(AR71XX_RST_RESET);
134211476Sadrian	ATH_WRITE_REG(AR71XX_RST_RESET, reg & ~mask);
135211476Sadrian}
136211476Sadrian
137211476Sadrianstatic int
138211476Sadrianar71xx_chip_device_stopped(uint32_t mask)
139211476Sadrian{
140211476Sadrian	uint32_t reg;
141211476Sadrian
142211476Sadrian	reg = ATH_READ_REG(AR71XX_RST_RESET);
143228450Sadrian	return ((reg & mask) == mask);
144211476Sadrian}
145211476Sadrian
146234326Sadrianvoid
147233081Sadrianar71xx_chip_set_mii_speed(uint32_t unit, uint32_t speed)
148233081Sadrian{
149233081Sadrian	uint32_t val, reg, ctrl;
150233081Sadrian
151233081Sadrian	switch (unit) {
152233081Sadrian	case 0:
153233081Sadrian		reg = AR71XX_MII0_CTRL;
154233081Sadrian		break;
155233081Sadrian	case 1:
156233081Sadrian		reg = AR71XX_MII1_CTRL;
157233081Sadrian		break;
158233081Sadrian	default:
159233081Sadrian		printf("%s: invalid MII unit set for arge unit: %d\n",
160233081Sadrian		    __func__, unit);
161233081Sadrian		return;
162233081Sadrian	}
163233081Sadrian
164233081Sadrian	switch (speed) {
165233081Sadrian	case 10:
166233081Sadrian		ctrl = MII_CTRL_SPEED_10;
167233081Sadrian		break;
168233081Sadrian	case 100:
169233081Sadrian		ctrl = MII_CTRL_SPEED_100;
170233081Sadrian		break;
171233081Sadrian	case 1000:
172233081Sadrian		ctrl = MII_CTRL_SPEED_1000;
173233081Sadrian		break;
174233081Sadrian	default:
175233081Sadrian		printf("%s: invalid MII speed (%d) set for arge unit: %d\n",
176233081Sadrian		    __func__, speed, unit);
177233081Sadrian		return;
178233081Sadrian	}
179233081Sadrian
180233081Sadrian	val = ATH_READ_REG(reg);
181233081Sadrian	val &= ~(MII_CTRL_SPEED_MASK << MII_CTRL_SPEED_SHIFT);
182233081Sadrian	val |= (ctrl & MII_CTRL_SPEED_MASK) << MII_CTRL_SPEED_SHIFT;
183233081Sadrian	ATH_WRITE_REG(reg, val);
184233081Sadrian}
185233081Sadrian
186234906Sadrianvoid
187234906Sadrianar71xx_chip_set_mii_if(uint32_t unit, uint32_t mii_mode)
188234906Sadrian{
189234906Sadrian	uint32_t val, reg, mii_if;
190234906Sadrian
191234906Sadrian	switch (unit) {
192234906Sadrian	case 0:
193234906Sadrian		reg = AR71XX_MII0_CTRL;
194234906Sadrian		if (mii_mode == AR71XX_MII_MODE_GMII)
195234906Sadrian			mii_if = MII0_CTRL_IF_GMII;
196234906Sadrian		else if (mii_mode == AR71XX_MII_MODE_MII)
197234906Sadrian			mii_if = MII0_CTRL_IF_MII;
198234906Sadrian		else if (mii_mode == AR71XX_MII_MODE_RGMII)
199234906Sadrian			mii_if = MII0_CTRL_IF_RGMII;
200234906Sadrian		else if (mii_mode == AR71XX_MII_MODE_RMII)
201234906Sadrian			mii_if = MII0_CTRL_IF_RMII;
202234941Sadrian		else {
203234906Sadrian			printf("%s: invalid MII mode (%d) for unit %d\n",
204234906Sadrian			    __func__, mii_mode, unit);
205234906Sadrian			return;
206234941Sadrian		}
207234906Sadrian		break;
208234906Sadrian	case 1:
209234906Sadrian		reg = AR71XX_MII1_CTRL;
210234906Sadrian		if (mii_mode == AR71XX_MII_MODE_RGMII)
211234906Sadrian			mii_if = MII1_CTRL_IF_RGMII;
212234941Sadrian		else if (mii_mode == AR71XX_MII_MODE_RMII)
213234906Sadrian			mii_if = MII1_CTRL_IF_RMII;
214234941Sadrian		else {
215234906Sadrian			printf("%s: invalid MII mode (%d) for unit %d\n",
216234906Sadrian			    __func__, mii_mode, unit);
217234906Sadrian			return;
218234941Sadrian		}
219234906Sadrian		break;
220234906Sadrian	default:
221234906Sadrian		printf("%s: invalid MII unit set for arge unit: %d\n",
222234906Sadrian		    __func__, unit);
223234906Sadrian		return;
224234906Sadrian	}
225234906Sadrian
226234906Sadrian	val = ATH_READ_REG(reg);
227234906Sadrian	val &= ~(MII_CTRL_IF_MASK << MII_CTRL_IF_SHIFT);
228234906Sadrian	val |= (mii_if & MII_CTRL_IF_MASK) << MII_CTRL_IF_SHIFT;
229234906Sadrian	ATH_WRITE_REG(reg, val);
230234906Sadrian}
231234906Sadrian
232211510Sadrian/* Speed is either 10, 100 or 1000 */
233211476Sadrianstatic void
234234907Sadrianar71xx_chip_set_pll_ge(int unit, int speed, uint32_t pll)
235211476Sadrian{
236211510Sadrian
237228018Sray	switch (unit) {
238228018Sray	case 0:
239228018Sray		ar71xx_write_pll(AR71XX_PLL_SEC_CONFIG,
240228018Sray		    AR71XX_PLL_ETH_INT0_CLK, pll,
241228018Sray		    AR71XX_PLL_ETH0_SHIFT);
242228018Sray		break;
243228018Sray	case 1:
244228018Sray		ar71xx_write_pll(AR71XX_PLL_SEC_CONFIG,
245228018Sray		    AR71XX_PLL_ETH_INT1_CLK, pll,
246228018Sray		    AR71XX_PLL_ETH1_SHIFT);
247228018Sray		break;
248228018Sray	default:
249228018Sray		printf("%s: invalid PLL set for arge unit: %d\n",
250228018Sray		    __func__, unit);
251228018Sray		return;
252228018Sray	}
253211476Sadrian}
254211476Sadrian
255211476Sadrianstatic void
256228018Srayar71xx_chip_ddr_flush_ge(int unit)
257211476Sadrian{
258228450Sadrian
259228018Sray	switch (unit) {
260228018Sray	case 0:
261228018Sray		ar71xx_ddr_flush(AR71XX_WB_FLUSH_GE0);
262228018Sray		break;
263228018Sray	case 1:
264228018Sray		ar71xx_ddr_flush(AR71XX_WB_FLUSH_GE1);
265228018Sray		break;
266228018Sray	default:
267228018Sray		printf("%s: invalid DDR flush for arge unit: %d\n",
268228018Sray		    __func__, unit);
269228018Sray		return;
270211510Sadrian	}
271211476Sadrian}
272211476Sadrian
273211476Sadrianstatic void
274221240Sadrianar71xx_chip_ddr_flush_ip2(void)
275221240Sadrian{
276221240Sadrian	ar71xx_ddr_flush(AR71XX_WB_FLUSH_PCI);
277221240Sadrian}
278221240Sadrian
279211476Sadrianstatic uint32_t
280211476Sadrianar71xx_chip_get_eth_pll(unsigned int mac, int speed)
281211476Sadrian{
282234907Sadrian	uint32_t pll;
283234907Sadrian
284234907Sadrian	switch (speed) {
285234907Sadrian	case 10:
286234907Sadrian		pll = PLL_ETH_INT_CLK_10;
287234907Sadrian		break;
288234907Sadrian	case 100:
289234907Sadrian		pll = PLL_ETH_INT_CLK_100;
290234907Sadrian		break;
291234907Sadrian	case 1000:
292234907Sadrian		pll = PLL_ETH_INT_CLK_1000;
293234907Sadrian		break;
294234907Sadrian	default:
295234907Sadrian		printf("%s%d: invalid speed %d\n", __func__, mac, speed);
296234907Sadrian		pll = 0;
297234907Sadrian	}
298234907Sadrian
299234907Sadrian	return (pll);
300211476Sadrian}
301211476Sadrian
302211476Sadrianstatic void
303211476Sadrianar71xx_chip_init_usb_peripheral(void)
304211476Sadrian{
305228450Sadrian
306228450Sadrian	ar71xx_device_stop(RST_RESET_USB_OHCI_DLL |
307228450Sadrian	    RST_RESET_USB_HOST | RST_RESET_USB_PHY);
308211476Sadrian	DELAY(1000);
309211476Sadrian
310228450Sadrian	ar71xx_device_start(RST_RESET_USB_OHCI_DLL |
311228450Sadrian	    RST_RESET_USB_HOST | RST_RESET_USB_PHY);
312211476Sadrian	DELAY(1000);
313211476Sadrian
314211476Sadrian	ATH_WRITE_REG(AR71XX_USB_CTRL_CONFIG,
315228450Sadrian	    USB_CTRL_CONFIG_OHCI_DES_SWAP |
316228450Sadrian	    USB_CTRL_CONFIG_OHCI_BUF_SWAP |
317228450Sadrian	    USB_CTRL_CONFIG_EHCI_DES_SWAP |
318228450Sadrian	    USB_CTRL_CONFIG_EHCI_BUF_SWAP);
319211476Sadrian
320211476Sadrian	ATH_WRITE_REG(AR71XX_USB_CTRL_FLADJ,
321228450Sadrian	    (32 << USB_CTRL_FLADJ_HOST_SHIFT) |
322228450Sadrian	    (3 << USB_CTRL_FLADJ_A5_SHIFT));
323211476Sadrian
324211476Sadrian	DELAY(1000);
325211476Sadrian}
326211476Sadrian
327211476Sadrianstruct ar71xx_cpu_def ar71xx_chip_def = {
328211476Sadrian	&ar71xx_chip_detect_mem_size,
329211476Sadrian	&ar71xx_chip_detect_sys_frequency,
330211476Sadrian	&ar71xx_chip_device_stop,
331211476Sadrian	&ar71xx_chip_device_start,
332211476Sadrian	&ar71xx_chip_device_stopped,
333228018Sray	&ar71xx_chip_set_pll_ge,
334233081Sadrian	&ar71xx_chip_set_mii_speed,
335234906Sadrian	&ar71xx_chip_set_mii_if,
336228018Sray	&ar71xx_chip_ddr_flush_ge,
337211476Sadrian	&ar71xx_chip_get_eth_pll,
338221240Sadrian	&ar71xx_chip_ddr_flush_ip2,
339211476Sadrian	&ar71xx_chip_init_usb_peripheral,
340211476Sadrian};
341