ar71xx_machdep.c revision 220056
1228753Smm/*-
2228753Smm * Copyright (c) 2009 Oleksandr Tymoshenko
3228753Smm * All rights reserved.
4228753Smm *
5228753Smm * Redistribution and use in source and binary forms, with or without
6228753Smm * modification, are permitted provided that the following conditions
7228753Smm * are met:
8228753Smm * 1. Redistributions of source code must retain the above copyright
9228753Smm *    notice, this list of conditions and the following disclaimer.
10228753Smm * 2. Redistributions in binary form must reproduce the above copyright
11228753Smm *    notice, this list of conditions and the following disclaimer in the
12228753Smm *    documentation and/or other materials provided with the distribution.
13228753Smm *
14228753Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15228753Smm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16228753Smm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17228753Smm * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18228753Smm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19228753Smm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20228753Smm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21228753Smm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22228753Smm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23228753Smm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24228753Smm * SUCH DAMAGE.
25228753Smm */
26228753Smm
27228763Smm#include <sys/cdefs.h>
28228753Smm__FBSDID("$FreeBSD: head/sys/mips/atheros/ar71xx_machdep.c 220056 2011-03-27 13:55:35Z adrian $");
29228753Smm
30228753Smm#include <sys/param.h>
31228753Smm#include <machine/cpuregs.h>
32228753Smm
33228753Smm#include <mips/sentry5/s5reg.h>
34228753Smm
35228753Smm#include "opt_ddb.h"
36228753Smm
37228753Smm#include <sys/param.h>
38228753Smm#include <sys/conf.h>
39228753Smm#include <sys/kernel.h>
40228753Smm#include <sys/systm.h>
41228753Smm#include <sys/bus.h>
42228753Smm#include <sys/cons.h>
43228753Smm#include <sys/kdb.h>
44228753Smm#include <sys/reboot.h>
45228753Smm
46228753Smm#include <vm/vm.h>
47228753Smm#include <vm/vm_page.h>
48228753Smm
49228753Smm#include <net/ethernet.h>
50228753Smm
51228753Smm#include <machine/clock.h>
52228753Smm#include <machine/cpu.h>
53228753Smm#include <machine/hwfunc.h>
54228753Smm#include <machine/md_var.h>
55228753Smm#include <machine/trap.h>
56228753Smm#include <machine/vmparam.h>
57228753Smm
58228753Smm#include <mips/atheros/ar71xxreg.h>
59228753Smm
60228753Smm#include <mips/atheros/ar71xx_setup.h>
61228753Smm#include <mips/atheros/ar71xx_cpudef.h>
62228753Smm
63228753Smmextern char edata[], end[];
64228753Smm
65228753Smmuint32_t ar711_base_mac[ETHER_ADDR_LEN];
66228753Smm/* 4KB static data aread to keep a copy of the bootload env until
67228753Smm   the dynamic kenv is setup */
68228753Smmchar boot1_env[4096];
69228753Smm
70228753Smm/*
71228753Smm * We get a string in from Redboot with the all the arguments together,
72228753Smm * "foo=bar bar=baz". Split them up and save in kenv.
73228753Smm */
74228753Smmstatic void
75228753Smmparse_argv(char *str)
76228753Smm{
77228753Smm	char *n, *v;
78228753Smm
79228753Smm	while ((v = strsep(&str, " ")) != NULL) {
80228753Smm		if (*v == '\0')
81228753Smm			continue;
82228753Smm		if (*v == '-') {
83228753Smm			while (*v != '\0') {
84228753Smm				v++;
85228753Smm				switch (*v) {
86228753Smm				case 'a': boothowto |= RB_ASKNAME; break;
87228753Smm				case 'd': boothowto |= RB_KDB; break;
88				case 'g': boothowto |= RB_GDB; break;
89				case 's': boothowto |= RB_SINGLE; break;
90				case 'v': boothowto |= RB_VERBOSE; break;
91				}
92			}
93		} else {
94			n = strsep(&v, "=");
95			if (v == NULL)
96				setenv(n, "1");
97			else
98				setenv(n, v);
99		}
100	}
101}
102
103void
104platform_cpu_init()
105{
106	/* Nothing special */
107}
108
109void
110platform_halt(void)
111{
112
113}
114
115void
116platform_identify(void)
117{
118
119}
120
121void
122platform_reset(void)
123{
124	ar71xx_device_stop(RST_RESET_FULL_CHIP);
125	/* Wait for reset */
126	while(1)
127		;
128}
129
130void
131platform_trap_enter(void)
132{
133
134}
135
136void
137platform_trap_exit(void)
138{
139
140}
141
142/*
143 * Obtain the MAC address via the Redboot environment.
144 */
145static void
146ar71xx_redboot_get_macaddr(void)
147{
148	char *var;
149	int count = 0;
150
151	/*
152	 * "ethaddr" is passed via envp on RedBoot platforms
153	 * "kmac" is passed via argv on RouterBOOT platforms
154	 */
155	if ((var = getenv("ethaddr")) != NULL ||
156	    (var = getenv("kmac")) != NULL) {
157		count = sscanf(var, "%x%*c%x%*c%x%*c%x%*c%x%*c%x",
158		    &ar711_base_mac[0], &ar711_base_mac[1],
159		    &ar711_base_mac[2], &ar711_base_mac[3],
160		    &ar711_base_mac[4], &ar711_base_mac[5]);
161		if (count < 6)
162			memset(ar711_base_mac, 0,
163			    sizeof(ar711_base_mac));
164		freeenv(var);
165	}
166}
167
168void
169platform_start(__register_t a0 __unused, __register_t a1 __unused,
170    __register_t a2 __unused, __register_t a3 __unused)
171{
172	uint64_t platform_counter_freq;
173	int argc, i;
174	char **argv, **envp;
175	vm_offset_t kernend;
176
177	/*
178	 * clear the BSS and SBSS segments, this should be first call in
179	 * the function
180	 */
181	kernend = (vm_offset_t)&end;
182	memset(&edata, 0, kernend - (vm_offset_t)(&edata));
183
184	mips_postboot_fixup();
185
186	/* Initialize pcpu stuff */
187	mips_pcpu0_init();
188
189	argc = a0;
190	argv = (char**)a1;
191	envp = (char**)a2;
192	/*
193	 * Protect ourselves from garbage in registers
194	 */
195	if (MIPS_IS_VALID_PTR(envp)) {
196		for (i = 0; envp[i]; i += 2) {
197			if (strcmp(envp[i], "memsize") == 0)
198				realmem = btoc(strtoul(envp[i+1], NULL, 16));
199		}
200	}
201
202	/*
203	 * Just wild guess. RedBoot let us down and didn't reported
204	 * memory size
205	 */
206	if (realmem == 0)
207		realmem = btoc(32*1024*1024);
208
209	/*
210	 * Allow build-time override in case Redboot lies
211	 * or in other situations (eg where there's u-boot)
212	 * where there isn't (yet) a convienent method of
213	 * being told how much RAM is available.
214	 *
215	 * This happens on at least the Ubiquiti LS-SR71A
216	 * board, where redboot says there's 16mb of RAM
217	 * but in fact there's 32mb.
218	 */
219#if	defined(AR71XX_REALMEM)
220		realmem = btoc(MIPS_REALMEM);
221#endif
222
223	/* phys_avail regions are in bytes */
224	phys_avail[0] = MIPS_KSEG0_TO_PHYS(kernel_kseg0_end);
225	phys_avail[1] = ctob(realmem);
226
227	dump_avail[0] = phys_avail[0];
228	dump_avail[1] = phys_avail[1] - phys_avail[0];
229
230	physmem = realmem;
231
232	/*
233	 * ns8250 uart code uses DELAY so ticker should be inititalized
234	 * before cninit. And tick_init_params refers to hz, so * init_param1
235	 * should be called first.
236	 */
237	init_param1();
238
239	/* Detect the system type - this is needed for subsequent chipset-specific calls */
240	ar71xx_detect_sys_type();
241	ar71xx_detect_sys_frequency();
242
243	platform_counter_freq = ar71xx_cpu_freq();
244	mips_timer_init_params(platform_counter_freq, 1);
245	cninit();
246	init_static_kenv(boot1_env, sizeof(boot1_env));
247
248	printf("CPU platform: %s\n", ar71xx_get_system_type());
249	printf("CPU Frequency=%d MHz\n", u_ar71xx_cpu_freq / 1000000);
250	printf("CPU DDR Frequency=%d MHz\n", u_ar71xx_ddr_freq / 1000000);
251	printf("CPU AHB Frequency=%d MHz\n", u_ar71xx_ahb_freq / 1000000);
252
253	printf("platform frequency: %lld\n", platform_counter_freq);
254	printf("arguments: \n");
255	printf("  a0 = %08x\n", a0);
256	printf("  a1 = %08x\n", a1);
257	printf("  a2 = %08x\n", a2);
258	printf("  a3 = %08x\n", a3);
259
260	printf("Cmd line:");
261	if (MIPS_IS_VALID_PTR(argv)) {
262		for (i = 0; i < argc; i++) {
263			printf(" %s", argv[i]);
264			parse_argv(argv[i]);
265		}
266	}
267	else
268		printf ("argv is invalid");
269	printf("\n");
270
271	printf("Environment:\n");
272	if (MIPS_IS_VALID_PTR(envp)) {
273		for (i = 0; envp[i]; i+=2) {
274			printf("  %s = %s\n", envp[i], envp[i+1]);
275			setenv(envp[i], envp[i+1]);
276		}
277	}
278	else
279		printf ("envp is invalid\n");
280
281	/* Redboot if_arge MAC address is in the environment */
282	ar71xx_redboot_get_macaddr();
283
284	init_param2(physmem);
285	mips_cpu_init();
286	pmap_bootstrap();
287	mips_proc0_init();
288	mutex_init();
289
290	/*
291	 * Reset USB devices
292	 */
293	ar71xx_init_usb_peripheral();
294
295	kdb_init();
296#ifdef KDB
297	if (boothowto & RB_KDB)
298		kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger");
299#endif
300}
301