ar71xx_machdep.c revision 198669
1/*-
2 * Copyright (c) 2009 Oleksandr Tymoshenko
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD$");
29
30#include <sys/param.h>
31#include <machine/cpuregs.h>
32
33#include <mips/sentry5/s5reg.h>
34
35#include "opt_ddb.h"
36
37#include <sys/param.h>
38#include <sys/conf.h>
39#include <sys/kernel.h>
40#include <sys/systm.h>
41#include <sys/bus.h>
42#include <sys/cons.h>
43#include <sys/kdb.h>
44#include <sys/reboot.h>
45
46#include <vm/vm.h>
47#include <vm/vm_page.h>
48
49#include <net/ethernet.h>
50
51#include <machine/clock.h>
52#include <machine/cpu.h>
53#include <machine/hwfunc.h>
54#include <machine/md_var.h>
55#include <machine/trap.h>
56#include <machine/vmparam.h>
57
58#include <mips/atheros/ar71xxreg.h>
59
60extern int *edata;
61extern int *end;
62uint32_t ar711_base_mac[ETHER_ADDR_LEN];
63/* 4KB static data aread to keep a copy of the bootload env until
64   the dynamic kenv is setup */
65char boot1_env[4096];
66
67/*
68 * We get a string in from Redboot with the all the arguments together,
69 * "foo=bar bar=baz". Split them up and save in kenv.
70 */
71static void
72parse_argv(char *str)
73{
74	char *n, *v;
75
76	while ((v = strsep(&str, " ")) != NULL) {
77		if (*v == '\0')
78			continue;
79		if (*v == '-') {
80			while (*v != '\0') {
81				v++;
82				switch (*v) {
83				case 'a': boothowto |= RB_ASKNAME; break;
84				case 'd': boothowto |= RB_KDB; break;
85				case 'g': boothowto |= RB_GDB; break;
86				case 's': boothowto |= RB_SINGLE; break;
87				case 'v': boothowto |= RB_VERBOSE; break;
88				}
89			}
90		} else {
91			n = strsep(&v, "=");
92			if (v == NULL)
93				setenv(n, "1");
94			else
95				setenv(n, v);
96		}
97	}
98}
99
100void
101platform_cpu_init()
102{
103	/* Nothing special */
104}
105
106void
107platform_halt(void)
108{
109
110}
111
112void
113platform_identify(void)
114{
115
116}
117
118void
119platform_reset(void)
120{
121	uint32_t reg = ATH_READ_REG(AR71XX_RST_RESET);
122
123	ATH_WRITE_REG(AR71XX_RST_RESET, reg | RST_RESET_FULL_CHIP);
124	/* Wait for reset */
125	while(1)
126		;
127}
128
129void
130platform_trap_enter(void)
131{
132
133}
134
135void
136platform_trap_exit(void)
137{
138
139}
140
141void
142platform_start(__register_t a0 __unused, __register_t a1 __unused,
143    __register_t a2 __unused, __register_t a3 __unused)
144{
145	vm_offset_t kernend;
146	uint64_t platform_counter_freq;
147	uint32_t reg;
148	int argc, i, count = 0;
149	char **argv, **envp;
150
151	/* clear the BSS and SBSS segments */
152	kernend = round_page((vm_offset_t)&end);
153	memset(&edata, 0, kernend - (vm_offset_t)(&edata));
154
155	argc = a0;
156	argv = (char**)a1;
157	envp = (char**)a2;
158	/*
159	 * Protect ourselves from garbage in registers
160	 */
161	if (MIPS_IS_VALID_PTR(envp)) {
162		for (i = 0; envp[i]; i += 2)
163		{
164			if (strcmp(envp[i], "memsize") == 0)
165				realmem = btoc(strtoul(envp[i+1], NULL, 16));
166			else if (strcmp(envp[i], "ethaddr") == 0) {
167				count = sscanf(envp[i+1], "%x.%x.%x.%x.%x.%x",
168				    &ar711_base_mac[0], &ar711_base_mac[1],
169				    &ar711_base_mac[2], &ar711_base_mac[3],
170				    &ar711_base_mac[4], &ar711_base_mac[5]);
171				if (count < 6)
172					memset(ar711_base_mac, 0,
173					    sizeof(ar711_base_mac));
174			}
175		}
176	}
177
178	/*
179	 * Just wild guess. RedBoot let us down and didn't reported
180	 * memory size
181	 */
182	if (realmem == 0)
183		realmem = btoc(32*1024*1024);
184
185	/* phys_avail regions are in bytes */
186	phys_avail[0] = MIPS_KSEG0_TO_PHYS((vm_offset_t)&end);
187	phys_avail[1] = ctob(realmem);
188
189	physmem = realmem;
190
191	/*
192	 * ns8250 uart code uses DELAY so ticker should be inititalized
193	 * before cninit. And tick_init_params refers to hz, so * init_param1
194	 * should be called first.
195	 */
196	init_param1();
197	platform_counter_freq = ar71xx_cpu_freq();
198	mips_timer_init_params(platform_counter_freq, 1);
199	cninit();
200	init_static_kenv(boot1_env, sizeof(boot1_env));
201
202	printf("platform frequency: %lld\n", platform_counter_freq);
203	printf("arguments: \n");
204	printf("  a0 = %08x\n", a0);
205	printf("  a1 = %08x\n", a1);
206	printf("  a2 = %08x\n", a2);
207	printf("  a3 = %08x\n", a3);
208
209	printf("Cmd line:");
210	if (MIPS_IS_VALID_PTR(argv)) {
211		for (i = 0; i < argc; i++) {
212			printf(" %s", argv[i]);
213			parse_argv(argv[i]);
214		}
215	}
216	else
217		printf ("argv is invalid");
218	printf("\n");
219
220	printf("Environment:\n");
221	if (MIPS_IS_VALID_PTR(envp)) {
222		for (i = 0; envp[i]; i+=2) {
223			printf("  %s = %s\n", envp[i], envp[i+1]);
224			setenv(envp[i], envp[i+1]);
225		}
226	}
227	else
228		printf ("envp is invalid\n");
229
230	init_param2(physmem);
231	mips_cpu_init();
232	pmap_bootstrap();
233	mips_proc0_init();
234	mutex_init();
235
236	/*
237	 * Reset USB devices
238	 */
239	reg = ATH_READ_REG(AR71XX_RST_RESET);
240	reg |=
241	    RST_RESET_USB_OHCI_DLL | RST_RESET_USB_HOST | RST_RESET_USB_PHY;
242	ATH_WRITE_REG(AR71XX_RST_RESET, reg);
243	DELAY(1000);
244	reg &=
245	    ~(RST_RESET_USB_OHCI_DLL | RST_RESET_USB_HOST | RST_RESET_USB_PHY);
246	ATH_WRITE_REG(AR71XX_RST_RESET, reg);
247
248	ATH_WRITE_REG(AR71XX_USB_CTRL_CONFIG,
249	    USB_CTRL_CONFIG_OHCI_DES_SWAP | USB_CTRL_CONFIG_OHCI_BUF_SWAP |
250	    USB_CTRL_CONFIG_EHCI_DES_SWAP | USB_CTRL_CONFIG_EHCI_BUF_SWAP);
251
252	ATH_WRITE_REG(AR71XX_USB_CTRL_FLADJ,
253	    (32 << USB_CTRL_FLADJ_HOST_SHIFT) | (3 << USB_CTRL_FLADJ_A5_SHIFT));
254	DELAY(1000);
255
256#ifdef DDB
257	kdb_init();
258#endif
259}
260