ar71xx_chip.c revision 223562
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: head/sys/mips/atheros/ar71xx_chip.c 223562 2011-06-26 10:07:48Z kevlo $");
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>
40211476Sadrian
41211476Sadrian#include <vm/vm.h>
42211476Sadrian#include <vm/vm_page.h>
43211476Sadrian
44211476Sadrian#include <net/ethernet.h>
45211476Sadrian
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>
53211476Sadrian
54211476Sadrian#include <mips/atheros/ar71xxreg.h>
55211476Sadrian
56211476Sadrian#include <mips/atheros/ar71xx_chip.h>
57211476Sadrian
58211476Sadrian#include <mips/atheros/ar71xx_cpudef.h>
59211476Sadrian
60223562Skevlo#include <mips/sentry5/s5reg.h>
61223562Skevlo
62211476Sadrian/* XXX these should replace the current definitions in ar71xxreg.h */
63211476Sadrian/* XXX perhaps an ar71xx_chip.h header file? */
64211476Sadrian#define AR71XX_PLL_REG_CPU_CONFIG       AR71XX_PLL_CPU_BASE + 0x00
65211476Sadrian#define AR71XX_PLL_REG_SEC_CONFIG       AR71XX_PLL_CPU_BASE + 0x04
66211476Sadrian#define AR71XX_PLL_REG_ETH0_INT_CLOCK   AR71XX_PLL_CPU_BASE + 0x10
67211476Sadrian#define AR71XX_PLL_REG_ETH1_INT_CLOCK   AR71XX_PLL_CPU_BASE + 0x14
68211476Sadrian
69211476Sadrian#define AR71XX_PLL_DIV_SHIFT            3
70211476Sadrian#define AR71XX_PLL_DIV_MASK             0x1f
71211476Sadrian#define AR71XX_CPU_DIV_SHIFT            16
72211476Sadrian#define AR71XX_CPU_DIV_MASK             0x3
73211476Sadrian#define AR71XX_DDR_DIV_SHIFT            18
74211476Sadrian#define AR71XX_DDR_DIV_MASK             0x3
75211476Sadrian#define AR71XX_AHB_DIV_SHIFT            20
76211476Sadrian#define AR71XX_AHB_DIV_MASK             0x7
77211476Sadrian
78211476Sadrian/* XXX these shouldn't be in here - this file is a per-chip file */
79211476Sadrian/* XXX these should be in the top-level ar71xx type, not ar71xx -chip */
80211476Sadrianuint32_t u_ar71xx_cpu_freq;
81211476Sadrianuint32_t u_ar71xx_ahb_freq;
82211476Sadrianuint32_t u_ar71xx_ddr_freq;
83211476Sadrian
84211476Sadrianstatic void
85211476Sadrianar71xx_chip_detect_mem_size(void)
86211476Sadrian{
87211476Sadrian}
88211476Sadrian
89211476Sadrianstatic void
90211476Sadrianar71xx_chip_detect_sys_frequency(void)
91211476Sadrian{
92211476Sadrian	uint32_t pll;
93211476Sadrian	uint32_t freq;
94211476Sadrian	uint32_t div;
95211476Sadrian
96211476Sadrian	pll = ATH_READ_REG(AR71XX_PLL_REG_CPU_CONFIG);
97211476Sadrian
98211476Sadrian	div = ((pll >> AR71XX_PLL_DIV_SHIFT) & AR71XX_PLL_DIV_MASK) + 1;
99211476Sadrian	freq = div * AR71XX_BASE_FREQ;
100211476Sadrian
101211476Sadrian	div = ((pll >> AR71XX_CPU_DIV_SHIFT) & AR71XX_CPU_DIV_MASK) + 1;
102211476Sadrian	u_ar71xx_cpu_freq = freq / div;
103211476Sadrian
104211476Sadrian	div = ((pll >> AR71XX_DDR_DIV_SHIFT) & AR71XX_DDR_DIV_MASK) + 1;
105211476Sadrian	u_ar71xx_ddr_freq = freq / div;
106211476Sadrian
107211476Sadrian	div = (((pll >> AR71XX_AHB_DIV_SHIFT) & AR71XX_AHB_DIV_MASK) + 1) * 2;
108211476Sadrian	u_ar71xx_ahb_freq = u_ar71xx_cpu_freq / div;
109211476Sadrian}
110211476Sadrian
111211476Sadrian/*
112211476Sadrian * This does not lock the CPU whilst doing the work!
113211476Sadrian */
114211476Sadrianstatic void
115211476Sadrianar71xx_chip_device_stop(uint32_t mask)
116211476Sadrian{
117211476Sadrian	uint32_t reg;
118211476Sadrian
119211476Sadrian	reg = ATH_READ_REG(AR71XX_RST_RESET);
120211476Sadrian	ATH_WRITE_REG(AR71XX_RST_RESET, reg | mask);
121211476Sadrian}
122211476Sadrian
123211476Sadrianstatic void
124211476Sadrianar71xx_chip_device_start(uint32_t mask)
125211476Sadrian{
126211476Sadrian	uint32_t reg;
127211476Sadrian
128211476Sadrian	reg = ATH_READ_REG(AR71XX_RST_RESET);
129211476Sadrian	ATH_WRITE_REG(AR71XX_RST_RESET, reg & ~mask);
130211476Sadrian}
131211476Sadrian
132211476Sadrianstatic int
133211476Sadrianar71xx_chip_device_stopped(uint32_t mask)
134211476Sadrian{
135211476Sadrian	uint32_t reg;
136211476Sadrian
137211476Sadrian	reg = ATH_READ_REG(AR71XX_RST_RESET);
138211476Sadrian        return ((reg & mask) == mask);
139211476Sadrian}
140211476Sadrian
141211510Sadrian/* Speed is either 10, 100 or 1000 */
142211476Sadrianstatic void
143211476Sadrianar71xx_chip_set_pll_ge0(int speed)
144211476Sadrian{
145211510Sadrian	uint32_t pll;
146211510Sadrian
147211510Sadrian	switch(speed) {
148211510Sadrian		case 10:
149211510Sadrian			pll = PLL_ETH_INT_CLK_10;
150211510Sadrian			break;
151211510Sadrian		case 100:
152211510Sadrian			pll = PLL_ETH_INT_CLK_100;
153211510Sadrian			break;
154211510Sadrian		case 1000:
155211510Sadrian			pll = PLL_ETH_INT_CLK_1000;
156211510Sadrian			break;
157211510Sadrian		default:
158211510Sadrian			printf("ar71xx_chip_set_pll_ge0: invalid speed %d\n", speed);
159211510Sadrian			return;
160211510Sadrian	}
161211510Sadrian
162211510Sadrian	ar71xx_write_pll(AR71XX_PLL_SEC_CONFIG, AR71XX_PLL_ETH_INT0_CLK, pll, AR71XX_PLL_ETH0_SHIFT);
163211476Sadrian}
164211476Sadrian
165211476Sadrianstatic void
166211476Sadrianar71xx_chip_set_pll_ge1(int speed)
167211476Sadrian{
168211510Sadrian	uint32_t pll;
169211510Sadrian
170211510Sadrian	switch(speed) {
171211510Sadrian		case 10:
172211510Sadrian			pll = PLL_ETH_INT_CLK_10;
173211510Sadrian			break;
174211510Sadrian		case 100:
175211510Sadrian			pll = PLL_ETH_INT_CLK_100;
176211510Sadrian			break;
177211510Sadrian		case 1000:
178211510Sadrian			pll = PLL_ETH_INT_CLK_1000;
179211510Sadrian			break;
180211510Sadrian		default:
181211510Sadrian			printf("ar71xx_chip_set_pll_ge1: invalid speed %d\n", speed);
182211510Sadrian			return;
183211510Sadrian	}
184211510Sadrian
185211510Sadrian	ar71xx_write_pll(AR71XX_PLL_SEC_CONFIG, AR71XX_PLL_ETH_INT1_CLK, pll, AR71XX_PLL_ETH1_SHIFT);
186211476Sadrian}
187211476Sadrian
188211476Sadrianstatic void
189211476Sadrianar71xx_chip_ddr_flush_ge0(void)
190211476Sadrian{
191211476Sadrian	ar71xx_ddr_flush(AR71XX_WB_FLUSH_GE0);
192211476Sadrian}
193211476Sadrian
194211476Sadrianstatic void
195211476Sadrianar71xx_chip_ddr_flush_ge1(void)
196211476Sadrian{
197211476Sadrian	ar71xx_ddr_flush(AR71XX_WB_FLUSH_GE1);
198211476Sadrian}
199211476Sadrian
200221240Sadrianstatic void
201221240Sadrianar71xx_chip_ddr_flush_ip2(void)
202221240Sadrian{
203221240Sadrian	ar71xx_ddr_flush(AR71XX_WB_FLUSH_PCI);
204221240Sadrian}
205221240Sadrian
206211476Sadrianstatic uint32_t
207211476Sadrianar71xx_chip_get_eth_pll(unsigned int mac, int speed)
208211476Sadrian{
209211476Sadrian	return 0;
210211476Sadrian}
211211476Sadrian
212211476Sadrianstatic void
213211476Sadrianar71xx_chip_init_usb_peripheral(void)
214211476Sadrian{
215211476Sadrian	ar71xx_device_stop(RST_RESET_USB_OHCI_DLL | RST_RESET_USB_HOST | RST_RESET_USB_PHY);
216211476Sadrian	DELAY(1000);
217211476Sadrian
218211476Sadrian	ar71xx_device_start(RST_RESET_USB_OHCI_DLL | RST_RESET_USB_HOST | RST_RESET_USB_PHY);
219211476Sadrian	DELAY(1000);
220211476Sadrian
221211476Sadrian	ATH_WRITE_REG(AR71XX_USB_CTRL_CONFIG,
222211476Sadrian	    USB_CTRL_CONFIG_OHCI_DES_SWAP | USB_CTRL_CONFIG_OHCI_BUF_SWAP |
223211476Sadrian	    USB_CTRL_CONFIG_EHCI_DES_SWAP | USB_CTRL_CONFIG_EHCI_BUF_SWAP);
224211476Sadrian
225211476Sadrian	ATH_WRITE_REG(AR71XX_USB_CTRL_FLADJ,
226211476Sadrian	    (32 << USB_CTRL_FLADJ_HOST_SHIFT) | (3 << USB_CTRL_FLADJ_A5_SHIFT));
227211476Sadrian
228211476Sadrian	DELAY(1000);
229211476Sadrian}
230211476Sadrian
231211476Sadrianstruct ar71xx_cpu_def ar71xx_chip_def = {
232211476Sadrian	&ar71xx_chip_detect_mem_size,
233211476Sadrian	&ar71xx_chip_detect_sys_frequency,
234211476Sadrian	&ar71xx_chip_device_stop,
235211476Sadrian	&ar71xx_chip_device_start,
236211476Sadrian	&ar71xx_chip_device_stopped,
237211476Sadrian	&ar71xx_chip_set_pll_ge0,
238211476Sadrian	&ar71xx_chip_set_pll_ge1,
239211476Sadrian	&ar71xx_chip_ddr_flush_ge0,
240211476Sadrian	&ar71xx_chip_ddr_flush_ge1,
241211476Sadrian	&ar71xx_chip_get_eth_pll,
242221240Sadrian	&ar71xx_chip_ddr_flush_ip2,
243211476Sadrian	&ar71xx_chip_init_usb_peripheral,
244211476Sadrian};
245