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