diff options
Diffstat (limited to 'arch/mips/momentum/jaguar_atx/prom.c')
-rw-r--r-- | arch/mips/momentum/jaguar_atx/prom.c | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/arch/mips/momentum/jaguar_atx/prom.c b/arch/mips/momentum/jaguar_atx/prom.c new file mode 100644 index 000000000000..fa5982ac0ac6 --- /dev/null +++ b/arch/mips/momentum/jaguar_atx/prom.c @@ -0,0 +1,266 @@ +/* + * Copyright 2002 Momentum Computer Inc. + * Author: Matthew Dharm <mdharm@momenco.com> + * + * Louis Hamilton, Red Hat, Inc. + * hamilton@redhat.com [MIPS64 modifications] + * + * Based on Ocelot Linux port, which is + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * Added changes for SMP - Manish Lachwani (lachwani@pmc-sierra.com) + */ +#include <linux/config.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/bootmem.h> + +#include <asm/addrspace.h> +#include <asm/bootinfo.h> +#include <asm/mv64340.h> +#include <asm/pmon.h> + +#include "jaguar_atx_fpga.h" + +extern void ja_setup_console(void); + +struct callvectors *debug_vectors; + +extern unsigned long cpu_clock; + +const char *get_system_type(void) +{ + return "Momentum Jaguar-ATX"; +} + +#ifdef CONFIG_MV643XX_ETH +extern unsigned char prom_mac_addr_base[6]; + +static void burn_clocks(void) +{ + int i; + + /* this loop should burn at least 1us -- this should be plenty */ + for (i = 0; i < 0x10000; i++) + ; +} + +static u8 exchange_bit(u8 val, u8 cs) +{ + /* place the data */ + JAGUAR_FPGA_WRITE((val << 2) | cs, EEPROM_MODE); + burn_clocks(); + + /* turn the clock on */ + JAGUAR_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE); + burn_clocks(); + + /* turn the clock off and read-strobe */ + JAGUAR_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE); + + /* return the data */ + return ((JAGUAR_FPGA_READ(EEPROM_MODE) >> 3) & 0x1); +} + +void get_mac(char dest[6]) +{ + u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + int i,j; + + for (i = 0; i < 12; i++) + exchange_bit(read_opcode[i], 1); + + for (j = 0; j < 6; j++) { + dest[j] = 0; + for (i = 0; i < 8; i++) { + dest[j] <<= 1; + dest[j] |= exchange_bit(0, 1); + } + } + + /* turn off CS */ + exchange_bit(0,0); +} +#endif + +#ifdef CONFIG_MIPS64 + +unsigned long signext(unsigned long addr) +{ + addr &= 0xffffffff; + return (unsigned long)((int)addr); +} + +void *get_arg(unsigned long args, int arc) +{ + unsigned long ul; + unsigned char *puc, uc; + + args += (arc * 4); + ul = (unsigned long)signext(args); + puc = (unsigned char *)ul; + if (puc == 0) + return (void *)0; + +#ifdef CONFIG_CPU_LITTLE_ENDIAN + uc = *puc++; + l = (unsigned long)uc; + uc = *puc++; + ul |= (((unsigned long)uc) << 8); + uc = *puc++; + ul |= (((unsigned long)uc) << 16); + uc = *puc++; + ul |= (((unsigned long)uc) << 24); +#else + uc = *puc++; + ul = ((unsigned long)uc) << 24; + uc = *puc++; + ul |= (((unsigned long)uc) << 16); + uc = *puc++; + ul |= (((unsigned long)uc) << 8); + uc = *puc++; + ul |= ((unsigned long)uc); +#endif + ul = signext(ul); + + return (void *)ul; +} + +char *arg64(unsigned long addrin, int arg_index) +{ + unsigned long args; + char *p; + + args = signext(addrin); + p = (char *)get_arg(args, arg_index); + + return p; +} +#endif /* CONFIG_MIPS64 */ + +/* PMON passes arguments in C main() style */ +void __init prom_init(void) +{ + int argc = fw_arg0; + char **arg = (char **) fw_arg1; + char **env = (char **) fw_arg2; + struct callvectors *cv = (struct callvectors *) fw_arg3; + int i; + +#ifdef CONFIG_SERIAL_8250_CONSOLE +// ja_setup_console(); /* The very first thing. */ +#endif + +#ifdef CONFIG_MIPS64 + char *ptr; + + printk("Mips64 Jaguar-ATX\n"); + /* save the PROM vectors for debugging use */ + debug_vectors = (struct callvectors *)signext((unsigned long)cv); + + /* arg[0] is "g", the rest is boot parameters */ + arcs_cmdline[0] = '\0'; + + for (i = 1; i < argc; i++) { + ptr = (char *)arg64((unsigned long)arg, i); + if ((strlen(arcs_cmdline) + strlen(ptr) + 1) >= + sizeof(arcs_cmdline)) + break; + strcat(arcs_cmdline, ptr); + strcat(arcs_cmdline, " "); + } + + i = 0; + while (1) { + ptr = (char *)arg64((unsigned long)env, i); + if (! ptr) + break; + + if (strncmp("gtbase", ptr, strlen("gtbase")) == 0) { + marvell_base = simple_strtol(ptr + strlen("gtbase="), + NULL, 16); + + if ((marvell_base & 0xffffffff00000000) == 0) + marvell_base |= 0xffffffff00000000; + + printk("marvell_base set to 0x%016lx\n", marvell_base); + } + if (strncmp("cpuclock", ptr, strlen("cpuclock")) == 0) { + cpu_clock = simple_strtol(ptr + strlen("cpuclock="), + NULL, 10); + printk("cpu_clock set to %d\n", cpu_clock); + } + i++; + } + printk("arcs_cmdline: %s\n", arcs_cmdline); + +#else /* CONFIG_MIPS64 */ + /* save the PROM vectors for debugging use */ + debug_vectors = cv; + + /* arg[0] is "g", the rest is boot parameters */ + arcs_cmdline[0] = '\0'; + for (i = 1; i < argc; i++) { + if (strlen(arcs_cmdline) + strlen(arg[i] + 1) + >= sizeof(arcs_cmdline)) + break; + strcat(arcs_cmdline, arg[i]); + strcat(arcs_cmdline, " "); + } + + while (*env) { + if (strncmp("gtbase", *env, strlen("gtbase")) == 0) { + marvell_base = simple_strtol(*env + strlen("gtbase="), + NULL, 16); + } + if (strncmp("cpuclock", *env, strlen("cpuclock")) == 0) { + cpu_clock = simple_strtol(*env + strlen("cpuclock="), + NULL, 10); + } + env++; + } +#endif /* CONFIG_MIPS64 */ + mips_machgroup = MACH_GROUP_MOMENCO; + mips_machtype = MACH_MOMENCO_JAGUAR_ATX; + +#ifdef CONFIG_MV643XX_ETH + /* get the base MAC address for on-board ethernet ports */ + get_mac(prom_mac_addr_base); +#endif +} + +void __init prom_free_prom_memory(void) +{ +} + +void __init prom_fixup_mem_map(unsigned long start, unsigned long end) +{ +} + +int prom_boot_secondary(int cpu, unsigned long sp, unsigned long gp) +{ + /* Clear the semaphore */ + *(volatile uint32_t *)(0xbb000a68) = 0x80000000; + + return 1; +} + +void prom_init_secondary(void) +{ + clear_c0_config(CONF_CM_CMASK); + set_c0_config(0x2); + + clear_c0_status(ST0_IM); + set_c0_status(0x1ffff); +} + +void prom_smp_finish(void) +{ +} |