ar71xx_machdep.c revision 211480
1187423Sgonzo/*-
2187423Sgonzo * Copyright (c) 2009 Oleksandr Tymoshenko
3187423Sgonzo * All rights reserved.
4187423Sgonzo *
5187423Sgonzo * Redistribution and use in source and binary forms, with or without
6187423Sgonzo * modification, are permitted provided that the following conditions
7187423Sgonzo * are met:
8187423Sgonzo * 1. Redistributions of source code must retain the above copyright
9187423Sgonzo *    notice, this list of conditions and the following disclaimer.
10187423Sgonzo * 2. Redistributions in binary form must reproduce the above copyright
11187423Sgonzo *    notice, this list of conditions and the following disclaimer in the
12187423Sgonzo *    documentation and/or other materials provided with the distribution.
13187423Sgonzo *
14187423Sgonzo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15187423Sgonzo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16187423Sgonzo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17187423Sgonzo * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18187423Sgonzo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19187423Sgonzo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20187423Sgonzo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21187423Sgonzo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22187423Sgonzo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23187423Sgonzo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24187423Sgonzo * SUCH DAMAGE.
25187423Sgonzo */
26187423Sgonzo
27187423Sgonzo#include <sys/cdefs.h>
28187423Sgonzo__FBSDID("$FreeBSD: head/sys/mips/atheros/ar71xx_machdep.c 211480 2010-08-19 02:12:04Z adrian $");
29187423Sgonzo
30187423Sgonzo#include <sys/param.h>
31187423Sgonzo#include <machine/cpuregs.h>
32187423Sgonzo
33187423Sgonzo#include <mips/sentry5/s5reg.h>
34187423Sgonzo
35187423Sgonzo#include "opt_ddb.h"
36187423Sgonzo
37187423Sgonzo#include <sys/param.h>
38187423Sgonzo#include <sys/conf.h>
39187423Sgonzo#include <sys/kernel.h>
40187423Sgonzo#include <sys/systm.h>
41187423Sgonzo#include <sys/bus.h>
42187423Sgonzo#include <sys/cons.h>
43187423Sgonzo#include <sys/kdb.h>
44198562Sthompsa#include <sys/reboot.h>
45187423Sgonzo
46187423Sgonzo#include <vm/vm.h>
47187423Sgonzo#include <vm/vm_page.h>
48187423Sgonzo
49192178Sgonzo#include <net/ethernet.h>
50192178Sgonzo
51187423Sgonzo#include <machine/clock.h>
52187423Sgonzo#include <machine/cpu.h>
53187423Sgonzo#include <machine/hwfunc.h>
54187423Sgonzo#include <machine/md_var.h>
55187423Sgonzo#include <machine/trap.h>
56187423Sgonzo#include <machine/vmparam.h>
57187423Sgonzo
58187456Sgonzo#include <mips/atheros/ar71xxreg.h>
59187423Sgonzo
60211476Sadrian#include <mips/atheros/ar71xx_setup.h>
61211476Sadrian#include <mips/atheros/ar71xx_cpudef.h>
62211476Sadrian
63202954Sgonzoextern char edata[], end[];
64202954Sgonzo
65192178Sgonzouint32_t ar711_base_mac[ETHER_ADDR_LEN];
66198562Sthompsa/* 4KB static data aread to keep a copy of the bootload env until
67198562Sthompsa   the dynamic kenv is setup */
68198562Sthompsachar boot1_env[4096];
69187423Sgonzo
70198562Sthompsa/*
71198562Sthompsa * We get a string in from Redboot with the all the arguments together,
72198562Sthompsa * "foo=bar bar=baz". Split them up and save in kenv.
73198562Sthompsa */
74198562Sthompsastatic void
75198562Sthompsaparse_argv(char *str)
76198562Sthompsa{
77198562Sthompsa	char *n, *v;
78198562Sthompsa
79198562Sthompsa	while ((v = strsep(&str, " ")) != NULL) {
80198562Sthompsa		if (*v == '\0')
81198562Sthompsa			continue;
82198562Sthompsa		if (*v == '-') {
83198562Sthompsa			while (*v != '\0') {
84198562Sthompsa				v++;
85198562Sthompsa				switch (*v) {
86198562Sthompsa				case 'a': boothowto |= RB_ASKNAME; break;
87198562Sthompsa				case 'd': boothowto |= RB_KDB; break;
88198562Sthompsa				case 'g': boothowto |= RB_GDB; break;
89198562Sthompsa				case 's': boothowto |= RB_SINGLE; break;
90198562Sthompsa				case 'v': boothowto |= RB_VERBOSE; break;
91198562Sthompsa				}
92198562Sthompsa			}
93198562Sthompsa		} else {
94198562Sthompsa			n = strsep(&v, "=");
95198562Sthompsa			if (v == NULL)
96198562Sthompsa				setenv(n, "1");
97198562Sthompsa			else
98198562Sthompsa				setenv(n, v);
99198562Sthompsa		}
100198562Sthompsa	}
101198562Sthompsa}
102198562Sthompsa
103187423Sgonzovoid
104198669Srrsplatform_cpu_init()
105198669Srrs{
106198669Srrs	/* Nothing special */
107198669Srrs}
108198669Srrs
109198669Srrsvoid
110187423Sgonzoplatform_halt(void)
111187423Sgonzo{
112187423Sgonzo
113187423Sgonzo}
114187423Sgonzo
115187423Sgonzovoid
116187423Sgonzoplatform_identify(void)
117187423Sgonzo{
118187423Sgonzo
119187423Sgonzo}
120187423Sgonzo
121187423Sgonzovoid
122187423Sgonzoplatform_reset(void)
123187423Sgonzo{
124211480Sadrian	ar71xx_device_stop(RST_RESET_FULL_CHIP);
125187463Sgonzo	/* Wait for reset */
126187463Sgonzo	while(1)
127187463Sgonzo		;
128187423Sgonzo}
129187423Sgonzo
130187423Sgonzovoid
131187423Sgonzoplatform_trap_enter(void)
132187423Sgonzo{
133187423Sgonzo
134187423Sgonzo}
135187423Sgonzo
136187423Sgonzovoid
137187423Sgonzoplatform_trap_exit(void)
138187423Sgonzo{
139187423Sgonzo
140187423Sgonzo}
141187423Sgonzo
142187423Sgonzovoid
143187423Sgonzoplatform_start(__register_t a0 __unused, __register_t a1 __unused,
144187423Sgonzo    __register_t a2 __unused, __register_t a3 __unused)
145187423Sgonzo{
146195513Sgonzo	uint64_t platform_counter_freq;
147195513Sgonzo	uint32_t reg;
148192178Sgonzo	int argc, i, count = 0;
149192178Sgonzo	char **argv, **envp;
150202954Sgonzo	vm_offset_t kernend;
151187423Sgonzo
152202954Sgonzo	/*
153202954Sgonzo	 * clear the BSS and SBSS segments, this should be first call in
154202954Sgonzo	 * the function
155202954Sgonzo	 */
156202954Sgonzo	kernend = (vm_offset_t)&end;
157187423Sgonzo	memset(&edata, 0, kernend - (vm_offset_t)(&edata));
158187423Sgonzo
159202954Sgonzo	mips_postboot_fixup();
160202954Sgonzo
161201845Simp	/* Initialize pcpu stuff */
162201881Simp	mips_pcpu0_init();
163201845Simp
164192178Sgonzo	argc = a0;
165192178Sgonzo	argv = (char**)a1;
166192178Sgonzo	envp = (char**)a2;
167192178Sgonzo	/*
168192178Sgonzo	 * Protect ourselves from garbage in registers
169192178Sgonzo	 */
170192178Sgonzo	if (MIPS_IS_VALID_PTR(envp)) {
171192178Sgonzo		for (i = 0; envp[i]; i += 2)
172192178Sgonzo		{
173192178Sgonzo			if (strcmp(envp[i], "memsize") == 0)
174192178Sgonzo				realmem = btoc(strtoul(envp[i+1], NULL, 16));
175192178Sgonzo			else if (strcmp(envp[i], "ethaddr") == 0) {
176192178Sgonzo				count = sscanf(envp[i+1], "%x.%x.%x.%x.%x.%x",
177192178Sgonzo				    &ar711_base_mac[0], &ar711_base_mac[1],
178192178Sgonzo				    &ar711_base_mac[2], &ar711_base_mac[3],
179192178Sgonzo				    &ar711_base_mac[4], &ar711_base_mac[5]);
180192178Sgonzo				if (count < 6)
181192178Sgonzo					memset(ar711_base_mac, 0,
182192178Sgonzo					    sizeof(ar711_base_mac));
183192178Sgonzo			}
184192178Sgonzo		}
185192178Sgonzo	}
186192178Sgonzo
187192178Sgonzo	/*
188192178Sgonzo	 * Just wild guess. RedBoot let us down and didn't reported
189192178Sgonzo	 * memory size
190192178Sgonzo	 */
191192178Sgonzo	if (realmem == 0)
192192178Sgonzo		realmem = btoc(32*1024*1024);
193192178Sgonzo
194187424Sgonzo	/* phys_avail regions are in bytes */
195202954Sgonzo	phys_avail[0] = MIPS_KSEG0_TO_PHYS(kernel_kseg0_end);
196187424Sgonzo	phys_avail[1] = ctob(realmem);
197187423Sgonzo
198187424Sgonzo	physmem = realmem;
199187423Sgonzo
200187423Sgonzo	/*
201187424Sgonzo	 * ns8250 uart code uses DELAY so ticker should be inititalized
202187424Sgonzo	 * before cninit. And tick_init_params refers to hz, so * init_param1
203187424Sgonzo	 * should be called first.
204187424Sgonzo	 */
205187424Sgonzo	init_param1();
206211476Sadrian
207211476Sadrian	/* Detect the system type - this is needed for subsequent chipset-specific calls */
208211476Sadrian	ar71xx_detect_sys_type();
209211476Sadrian	ar71xx_detect_sys_frequency();
210211476Sadrian
211195513Sgonzo	platform_counter_freq = ar71xx_cpu_freq();
212192365Sgonzo	mips_timer_init_params(platform_counter_freq, 1);
213187424Sgonzo	cninit();
214198562Sthompsa	init_static_kenv(boot1_env, sizeof(boot1_env));
215187423Sgonzo
216211476Sadrian	printf("CPU platform: %s\n", ar71xx_get_system_type());
217211476Sadrian	printf("CPU Frequency=%d MHz\n", u_ar71xx_cpu_freq / 1000000);
218211476Sadrian	printf("CPU DDR Frequency=%d MHz\n", u_ar71xx_ddr_freq / 1000000);
219211476Sadrian	printf("CPU AHB Frequency=%d MHz\n", u_ar71xx_ahb_freq / 1000000);
220211476Sadrian
221192132Sgonzo	printf("platform frequency: %lld\n", platform_counter_freq);
222187424Sgonzo	printf("arguments: \n");
223187423Sgonzo	printf("  a0 = %08x\n", a0);
224187423Sgonzo	printf("  a1 = %08x\n", a1);
225187423Sgonzo	printf("  a2 = %08x\n", a2);
226187423Sgonzo	printf("  a3 = %08x\n", a3);
227187423Sgonzo
228192178Sgonzo	printf("Cmd line:");
229192178Sgonzo	if (MIPS_IS_VALID_PTR(argv)) {
230198562Sthompsa		for (i = 0; i < argc; i++) {
231192178Sgonzo			printf(" %s", argv[i]);
232198562Sthompsa			parse_argv(argv[i]);
233198562Sthompsa		}
234192178Sgonzo	}
235192178Sgonzo	else
236192178Sgonzo		printf ("argv is invalid");
237192178Sgonzo	printf("\n");
238192178Sgonzo
239192178Sgonzo	printf("Environment:\n");
240192178Sgonzo	if (MIPS_IS_VALID_PTR(envp)) {
241198562Sthompsa		for (i = 0; envp[i]; i+=2) {
242192178Sgonzo			printf("  %s = %s\n", envp[i], envp[i+1]);
243198562Sthompsa			setenv(envp[i], envp[i+1]);
244198562Sthompsa		}
245192178Sgonzo	}
246192178Sgonzo	else
247192178Sgonzo		printf ("envp is invalid\n");
248192178Sgonzo
249187424Sgonzo	init_param2(physmem);
250187424Sgonzo	mips_cpu_init();
251187424Sgonzo	pmap_bootstrap();
252187424Sgonzo	mips_proc0_init();
253187424Sgonzo	mutex_init();
254187423Sgonzo
255188882Sgonzo	/*
256188882Sgonzo	 * Reset USB devices
257188882Sgonzo	 */
258188882Sgonzo	reg = ATH_READ_REG(AR71XX_RST_RESET);
259188882Sgonzo	reg |=
260188882Sgonzo	    RST_RESET_USB_OHCI_DLL | RST_RESET_USB_HOST | RST_RESET_USB_PHY;
261188882Sgonzo	ATH_WRITE_REG(AR71XX_RST_RESET, reg);
262188882Sgonzo	DELAY(1000);
263188882Sgonzo	reg &=
264188882Sgonzo	    ~(RST_RESET_USB_OHCI_DLL | RST_RESET_USB_HOST | RST_RESET_USB_PHY);
265188882Sgonzo	ATH_WRITE_REG(AR71XX_RST_RESET, reg);
266188882Sgonzo
267188882Sgonzo	ATH_WRITE_REG(AR71XX_USB_CTRL_CONFIG,
268188882Sgonzo	    USB_CTRL_CONFIG_OHCI_DES_SWAP | USB_CTRL_CONFIG_OHCI_BUF_SWAP |
269188882Sgonzo	    USB_CTRL_CONFIG_EHCI_DES_SWAP | USB_CTRL_CONFIG_EHCI_BUF_SWAP);
270188882Sgonzo
271188882Sgonzo	ATH_WRITE_REG(AR71XX_USB_CTRL_FLADJ,
272188882Sgonzo	    (32 << USB_CTRL_FLADJ_HOST_SHIFT) | (3 << USB_CTRL_FLADJ_A5_SHIFT));
273188882Sgonzo	DELAY(1000);
274188882Sgonzo
275187424Sgonzo	kdb_init();
276202849Simp#ifdef KDB
277202849Simp	if (boothowto & RB_KDB)
278202849Simp		kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger");
279187423Sgonzo#endif
280187423Sgonzo}
281