diff options
Diffstat (limited to 'arch/mips/pmcs-msp71xx/msp_setup.c')
-rw-r--r-- | arch/mips/pmcs-msp71xx/msp_setup.c | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/arch/mips/pmcs-msp71xx/msp_setup.c b/arch/mips/pmcs-msp71xx/msp_setup.c new file mode 100644 index 000000000..a63b73610 --- /dev/null +++ b/arch/mips/pmcs-msp71xx/msp_setup.c @@ -0,0 +1,232 @@ +/* + * The generic setup file for PMC-Sierra MSP processors + * + * Copyright 2005-2007 PMC-Sierra, Inc, + * Author: Jun Sun, 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. + */ + +#include <linux/delay.h> + +#include <asm/bootinfo.h> +#include <asm/cacheflush.h> +#include <asm/idle.h> +#include <asm/r4kcache.h> +#include <asm/reboot.h> +#include <asm/smp-ops.h> +#include <asm/time.h> + +#include <msp_prom.h> +#include <msp_regs.h> + +#if defined(CONFIG_PMC_MSP7120_GW) +#include <msp_regops.h> +#define MSP_BOARD_RESET_GPIO 9 +#endif + +extern void msp_serial_setup(void); + +#if defined(CONFIG_PMC_MSP7120_EVAL) || \ + defined(CONFIG_PMC_MSP7120_GW) || \ + defined(CONFIG_PMC_MSP7120_FPGA) +/* + * Performs the reset for MSP7120-based boards + */ +void msp7120_reset(void) +{ + void *start, *end, *iptr; + + /* Diasble all interrupts */ + local_irq_disable(); +#ifdef CONFIG_SYS_SUPPORTS_MULTITHREADING + dvpe(); +#endif + + /* Cache the reset code of this function */ + __asm__ __volatile__ ( + " .set push \n" + " .set arch=r4000 \n" + " la %0,startpoint \n" + " la %1,endpoint \n" + " .set pop \n" + : "=r" (start), "=r" (end) + : + ); + + for (iptr = (void *)((unsigned int)start & ~(L1_CACHE_BYTES - 1)); + iptr < end; iptr += L1_CACHE_BYTES) + cache_op(Fill, iptr); + + __asm__ __volatile__ ( + "startpoint: \n" + ); + + /* Put the DDRC into self-refresh mode */ + DDRC_INDIRECT_WRITE(DDRC_CTL(10), 0xb, 1 << 16); + + /* + * IMPORTANT! + * DO NOT do anything from here on out that might even + * think about fetching from RAM - i.e., don't call any + * non-inlined functions, and be VERY sure that any inline + * functions you do call do NOT access any sort of RAM + * anywhere! + */ + + /* Wait a bit for the DDRC to settle */ + mdelay(125); + +#if defined(CONFIG_PMC_MSP7120_GW) + /* + * Set GPIO 9 HI, (tied to board reset logic) + * GPIO 9 is the 4th GPIO of register 3 + * + * NOTE: We cannot use the higher-level msp_gpio_mode()/out() + * as GPIO char driver may not be enabled and it would look up + * data inRAM! + */ + set_value_reg32(GPIO_CFG3_REG, 0xf000, 0x8000); + set_reg32(GPIO_DATA3_REG, 8); + + /* + * In case GPIO9 doesn't reset the board (jumper configurable!) + * fallback to device reset below. + */ +#endif + /* Set bit 1 of the MSP7120 reset register */ + *RST_SET_REG = 0x00000001; + + __asm__ __volatile__ ( + "endpoint: \n" + ); +} +#endif + +void msp_restart(char *command) +{ + printk(KERN_WARNING "Now rebooting .......\n"); + +#if defined(CONFIG_PMC_MSP7120_EVAL) || \ + defined(CONFIG_PMC_MSP7120_GW) || \ + defined(CONFIG_PMC_MSP7120_FPGA) + msp7120_reset(); +#else + /* No chip-specific reset code, just jump to the ROM reset vector */ + set_c0_status(ST0_BEV | ST0_ERL); + change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); + __flush_cache_all(); + write_c0_wired(0); + + __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); +#endif +} + +void msp_halt(void) +{ + printk(KERN_WARNING "\n** You can safely turn off the power\n"); + while (1) + /* If possible call official function to get CPU WARs */ + if (cpu_wait) + (*cpu_wait)(); + else + __asm__(".set\tmips3\n\t" "wait\n\t" ".set\tmips0"); +} + +void msp_power_off(void) +{ + msp_halt(); +} + +void __init plat_mem_setup(void) +{ + _machine_restart = msp_restart; + _machine_halt = msp_halt; + pm_power_off = msp_power_off; +} + +void __init prom_init(void) +{ + unsigned long family; + unsigned long revision; + + prom_argc = fw_arg0; + prom_argv = (char **)fw_arg1; + prom_envp = (char **)fw_arg2; + + /* + * Someday we can use this with PMON2000 to get a + * platform call prom routines for output etc. without + * having to use grody hacks. For now it's unused. + * + * struct callvectors *cv = (struct callvectors *) fw_arg3; + */ + family = identify_family(); + revision = identify_revision(); + + switch (family) { + case FAMILY_FPGA: + if (FPGA_IS_MSP4200(revision)) { + /* Old-style revision ID */ + mips_machtype = MACH_MSP4200_FPGA; + } else { + mips_machtype = MACH_MSP_OTHER; + } + break; + + case FAMILY_MSP4200: +#if defined(CONFIG_PMC_MSP4200_EVAL) + mips_machtype = MACH_MSP4200_EVAL; +#elif defined(CONFIG_PMC_MSP4200_GW) + mips_machtype = MACH_MSP4200_GW; +#else + mips_machtype = MACH_MSP_OTHER; +#endif + break; + + case FAMILY_MSP4200_FPGA: + mips_machtype = MACH_MSP4200_FPGA; + break; + + case FAMILY_MSP7100: +#if defined(CONFIG_PMC_MSP7120_EVAL) + mips_machtype = MACH_MSP7120_EVAL; +#elif defined(CONFIG_PMC_MSP7120_GW) + mips_machtype = MACH_MSP7120_GW; +#else + mips_machtype = MACH_MSP_OTHER; +#endif + break; + + case FAMILY_MSP7100_FPGA: + mips_machtype = MACH_MSP7120_FPGA; + break; + + default: + /* we don't recognize the machine */ + mips_machtype = MACH_UNKNOWN; + panic("***Bogosity factor five***, exiting"); + break; + } + + prom_init_cmdline(); + + prom_meminit(); + + /* + * Sub-system setup follows. + * Setup functions can either be called here or using the + * subsys_initcall mechanism (i.e. see msp_pci_setup). The + * order in which they are called can be changed by using the + * link order in arch/mips/pmc-sierra/msp71xx/Makefile. + * + * NOTE: Please keep sub-system specific initialization code + * in separate specific files. + */ + msp_serial_setup(); + + register_vsmp_smp_ops(); +} |