ar71xx_machdep.c revision 198562
11541Srgrimes/*-
21541Srgrimes * Copyright (c) 2009 Oleksandr Tymoshenko
31541Srgrimes * All rights reserved.
41541Srgrimes *
51541Srgrimes * Redistribution and use in source and binary forms, with or without
61541Srgrimes * modification, are permitted provided that the following conditions
71541Srgrimes * are met:
81541Srgrimes * 1. Redistributions of source code must retain the above copyright
91541Srgrimes *    notice, this list of conditions and the following disclaimer.
101541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111541Srgrimes *    notice, this list of conditions and the following disclaimer in the
121541Srgrimes *    documentation and/or other materials provided with the distribution.
131541Srgrimes *
141541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
151541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
161541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
171541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
181541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
191541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
201541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
211541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
221541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
231541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
241541Srgrimes * SUCH DAMAGE.
251541Srgrimes */
261541Srgrimes
271541Srgrimes#include <sys/cdefs.h>
281541Srgrimes__FBSDID("$FreeBSD$");
291541Srgrimes
301541Srgrimes#include <sys/param.h>
311541Srgrimes#include <machine/cpuregs.h>
321541Srgrimes
331541Srgrimes#include <mips/sentry5/s5reg.h>
341541Srgrimes
351541Srgrimes#include "opt_ddb.h"
361541Srgrimes
371541Srgrimes#include <sys/param.h>
381541Srgrimes#include <sys/conf.h>
399759Sbde#include <sys/kernel.h>
401541Srgrimes#include <sys/systm.h>
411541Srgrimes#include <sys/bus.h>
421541Srgrimes#include <sys/cons.h>
431541Srgrimes#include <sys/kdb.h>
441541Srgrimes#include <sys/reboot.h>
451541Srgrimes
461541Srgrimes#include <vm/vm.h>
471541Srgrimes#include <vm/vm_page.h>
481541Srgrimes
499507Sdg#include <net/ethernet.h>
501541Srgrimes
515455Sdg#include <machine/clock.h>
525455Sdg#include <machine/cpu.h>
539507Sdg#include <machine/hwfunc.h>
549507Sdg#include <machine/md_var.h>
559507Sdg#include <machine/trap.h>
569507Sdg#include <machine/vmparam.h>
579507Sdg
589507Sdg#include <mips/atheros/ar71xxreg.h>
591541Srgrimes
601541Srgrimesextern int *edata;
611541Srgrimesextern int *end;
621541Srgrimesuint32_t ar711_base_mac[ETHER_ADDR_LEN];
631541Srgrimes/* 4KB static data aread to keep a copy of the bootload env until
641541Srgrimes   the dynamic kenv is setup */
651541Srgrimeschar boot1_env[4096];
661541Srgrimes
671541Srgrimes/*
681541Srgrimes * We get a string in from Redboot with the all the arguments together,
691541Srgrimes * "foo=bar bar=baz". Split them up and save in kenv.
701541Srgrimes */
711541Srgrimesstatic void
721541Srgrimesparse_argv(char *str)
731541Srgrimes{
741541Srgrimes	char *n, *v;
751541Srgrimes
761541Srgrimes	while ((v = strsep(&str, " ")) != NULL) {
771541Srgrimes		if (*v == '\0')
789759Sbde			continue;
799759Sbde		if (*v == '-') {
809759Sbde			while (*v != '\0') {
819507Sdg				v++;
825455Sdg				switch (*v) {
837090Sbde				case 'a': boothowto |= RB_ASKNAME; break;
849507Sdg				case 'd': boothowto |= RB_KDB; break;
859507Sdg				case 'g': boothowto |= RB_GDB; break;
869507Sdg				case 's': boothowto |= RB_SINGLE; break;
875455Sdg				case 'v': boothowto |= RB_VERBOSE; break;
889507Sdg				}
895455Sdg			}
905455Sdg		} else {
919507Sdg			n = strsep(&v, "=");
925455Sdg			if (v == NULL)
935455Sdg				setenv(n, "1");
945455Sdg			else
951541Srgrimes				setenv(n, v);
961541Srgrimes		}
975455Sdg	}
98}
99
100void
101platform_halt(void)
102{
103
104}
105
106void
107platform_identify(void)
108{
109
110}
111
112void
113platform_reset(void)
114{
115	uint32_t reg = ATH_READ_REG(AR71XX_RST_RESET);
116
117	ATH_WRITE_REG(AR71XX_RST_RESET, reg | RST_RESET_FULL_CHIP);
118	/* Wait for reset */
119	while(1)
120		;
121}
122
123void
124platform_trap_enter(void)
125{
126
127}
128
129void
130platform_trap_exit(void)
131{
132
133}
134
135void
136platform_start(__register_t a0 __unused, __register_t a1 __unused,
137    __register_t a2 __unused, __register_t a3 __unused)
138{
139	vm_offset_t kernend;
140	uint64_t platform_counter_freq;
141	uint32_t reg;
142	int argc, i, count = 0;
143	char **argv, **envp;
144
145	/* clear the BSS and SBSS segments */
146	kernend = round_page((vm_offset_t)&end);
147	memset(&edata, 0, kernend - (vm_offset_t)(&edata));
148
149	argc = a0;
150	argv = (char**)a1;
151	envp = (char**)a2;
152	/*
153	 * Protect ourselves from garbage in registers
154	 */
155	if (MIPS_IS_VALID_PTR(envp)) {
156		for (i = 0; envp[i]; i += 2)
157		{
158			if (strcmp(envp[i], "memsize") == 0)
159				realmem = btoc(strtoul(envp[i+1], NULL, 16));
160			else if (strcmp(envp[i], "ethaddr") == 0) {
161				count = sscanf(envp[i+1], "%x.%x.%x.%x.%x.%x",
162				    &ar711_base_mac[0], &ar711_base_mac[1],
163				    &ar711_base_mac[2], &ar711_base_mac[3],
164				    &ar711_base_mac[4], &ar711_base_mac[5]);
165				if (count < 6)
166					memset(ar711_base_mac, 0,
167					    sizeof(ar711_base_mac));
168			}
169		}
170	}
171
172	/*
173	 * Just wild guess. RedBoot let us down and didn't reported
174	 * memory size
175	 */
176	if (realmem == 0)
177		realmem = btoc(32*1024*1024);
178
179	/* phys_avail regions are in bytes */
180	phys_avail[0] = MIPS_KSEG0_TO_PHYS((vm_offset_t)&end);
181	phys_avail[1] = ctob(realmem);
182
183	physmem = realmem;
184
185	/*
186	 * ns8250 uart code uses DELAY so ticker should be inititalized
187	 * before cninit. And tick_init_params refers to hz, so * init_param1
188	 * should be called first.
189	 */
190	init_param1();
191	platform_counter_freq = ar71xx_cpu_freq();
192	mips_timer_init_params(platform_counter_freq, 1);
193	cninit();
194	init_static_kenv(boot1_env, sizeof(boot1_env));
195
196	printf("platform frequency: %lld\n", platform_counter_freq);
197	printf("arguments: \n");
198	printf("  a0 = %08x\n", a0);
199	printf("  a1 = %08x\n", a1);
200	printf("  a2 = %08x\n", a2);
201	printf("  a3 = %08x\n", a3);
202
203	printf("Cmd line:");
204	if (MIPS_IS_VALID_PTR(argv)) {
205		for (i = 0; i < argc; i++) {
206			printf(" %s", argv[i]);
207			parse_argv(argv[i]);
208		}
209	}
210	else
211		printf ("argv is invalid");
212	printf("\n");
213
214	printf("Environment:\n");
215	if (MIPS_IS_VALID_PTR(envp)) {
216		for (i = 0; envp[i]; i+=2) {
217			printf("  %s = %s\n", envp[i], envp[i+1]);
218			setenv(envp[i], envp[i+1]);
219		}
220	}
221	else
222		printf ("envp is invalid\n");
223
224	init_param2(physmem);
225	mips_cpu_init();
226	pmap_bootstrap();
227	mips_proc0_init();
228	mutex_init();
229
230	/*
231	 * Reset USB devices
232	 */
233	reg = ATH_READ_REG(AR71XX_RST_RESET);
234	reg |=
235	    RST_RESET_USB_OHCI_DLL | RST_RESET_USB_HOST | RST_RESET_USB_PHY;
236	ATH_WRITE_REG(AR71XX_RST_RESET, reg);
237	DELAY(1000);
238	reg &=
239	    ~(RST_RESET_USB_OHCI_DLL | RST_RESET_USB_HOST | RST_RESET_USB_PHY);
240	ATH_WRITE_REG(AR71XX_RST_RESET, reg);
241
242	ATH_WRITE_REG(AR71XX_USB_CTRL_CONFIG,
243	    USB_CTRL_CONFIG_OHCI_DES_SWAP | USB_CTRL_CONFIG_OHCI_BUF_SWAP |
244	    USB_CTRL_CONFIG_EHCI_DES_SWAP | USB_CTRL_CONFIG_EHCI_BUF_SWAP);
245
246	ATH_WRITE_REG(AR71XX_USB_CTRL_FLADJ,
247	    (32 << USB_CTRL_FLADJ_HOST_SHIFT) | (3 << USB_CTRL_FLADJ_A5_SHIFT));
248	DELAY(1000);
249
250#ifdef DDB
251	kdb_init();
252#endif
253}
254