diff options
Diffstat (limited to 'arch/mips/pmcs-msp71xx/msp_setup.c')
| -rw-r--r-- | arch/mips/pmcs-msp71xx/msp_setup.c | 245 | 
1 files changed, 245 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 00000000000..1651cfdbfe7 --- /dev/null +++ b/arch/mips/pmcs-msp71xx/msp_setup.c @@ -0,0 +1,245 @@ +/* + * 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 <asm/bootinfo.h> +#include <asm/cacheflush.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); +extern void pmctwiled_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; +	register int i; + +	/* 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	mips3				\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 */ +	for (i = 0; i < 100000000; i++); + +#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; +} + +extern struct plat_smp_ops msp_smtc_smp_ops; + +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(); + +	if (register_vsmp_smp_ops()) { +#ifdef CONFIG_MIPS_MT_SMTC +		register_smp_ops(&msp_smtc_smp_ops); +#endif +	} + +#ifdef CONFIG_PMCTWILED +	/* +	 * Setup LED states before the subsys_initcall loads other +	 * dependent drivers/modules. +	 */ +	pmctwiled_setup(); +#endif +}  |