diff options
Diffstat (limited to 'arch/ppc/cpu/mpc8260/cpu_init.c')
| -rw-r--r-- | arch/ppc/cpu/mpc8260/cpu_init.c | 292 | 
1 files changed, 292 insertions, 0 deletions
| diff --git a/arch/ppc/cpu/mpc8260/cpu_init.c b/arch/ppc/cpu/mpc8260/cpu_init.c new file mode 100644 index 000000000..1d5277344 --- /dev/null +++ b/arch/ppc/cpu/mpc8260/cpu_init.c @@ -0,0 +1,292 @@ +/* + * (C) Copyright 2000-2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <mpc8260.h> +#include <asm/cpm_8260.h> +#include <ioports.h> + +DECLARE_GLOBAL_DATA_PTR; + +#if defined(CONFIG_BOARD_GET_CPU_CLK_F) +extern unsigned long board_get_cpu_clk_f (void); +#endif + +static void config_8260_ioports (volatile immap_t * immr) +{ +	int portnum; + +	for (portnum = 0; portnum < 4; portnum++) { +		uint pmsk = 0, +		     ppar = 0, +		     psor = 0, +		     pdir = 0, +		     podr = 0, +		     pdat = 0; +		iop_conf_t *iopc = (iop_conf_t *) & iop_conf_tab[portnum][0]; +		iop_conf_t *eiopc = iopc + 32; +		uint msk = 1; + +		/* +		 * NOTE: +		 * index 0 refers to pin 31, +		 * index 31 refers to pin 0 +		 */ +		while (iopc < eiopc) { +			if (iopc->conf) { +				pmsk |= msk; +				if (iopc->ppar) +					ppar |= msk; +				if (iopc->psor) +					psor |= msk; +				if (iopc->pdir) +					pdir |= msk; +				if (iopc->podr) +					podr |= msk; +				if (iopc->pdat) +					pdat |= msk; +			} + +			msk <<= 1; +			iopc++; +		} + +		if (pmsk != 0) { +			volatile ioport_t *iop = ioport_addr (immr, portnum); +			uint tpmsk = ~pmsk; + +			/* +			 * the (somewhat confused) paragraph at the +			 * bottom of page 35-5 warns that there might +			 * be "unknown behaviour" when programming +			 * PSORx and PDIRx, if PPARx = 1, so I +			 * decided this meant I had to disable the +			 * dedicated function first, and enable it +			 * last. +			 */ +			iop->ppar &= tpmsk; +			iop->psor = (iop->psor & tpmsk) | psor; +			iop->podr = (iop->podr & tpmsk) | podr; +			iop->pdat = (iop->pdat & tpmsk) | pdat; +			iop->pdir = (iop->pdir & tpmsk) | pdir; +			iop->ppar |= ppar; +		} +	} +} + +#define SET_VAL_MASK(a, b, mask) ((a & mask) | (b & ~mask)) +/* + * Breath some life into the CPU... + * + * Set up the memory map, + * initialize a bunch of registers, + * initialize the UPM's + */ +void cpu_init_f (volatile immap_t * immr) +{ +#if !defined(CONFIG_COGENT)		/* done in start.S for the cogent */ +	uint sccr; +#endif +#if defined(CONFIG_BOARD_GET_CPU_CLK_F) +	unsigned long cpu_clk; +#endif +	volatile memctl8260_t *memctl = &immr->im_memctl; +	extern void m8260_cpm_reset (void); + +	/* Pointer is writable since we allocated a register for it */ +	gd = (gd_t *) (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET); + +	/* Clear initial global data */ +	memset ((void *) gd, 0, sizeof (gd_t)); + +	/* RSR - Reset Status Register - clear all status (5-4) */ +	gd->reset_status = immr->im_clkrst.car_rsr; +	immr->im_clkrst.car_rsr = RSR_ALLBITS; + +	/* RMR - Reset Mode Register - contains checkstop reset enable (5-5) */ +	immr->im_clkrst.car_rmr = CONFIG_SYS_RMR; + +	/* BCR - Bus Configuration Register (4-25) */ +#if defined(CONFIG_SYS_BCR_60x) && (CONFIG_SYS_BCR_SINGLE) +	if (immr->im_siu_conf.sc_bcr & BCR_EBM) { +		immr->im_siu_conf.sc_bcr = SET_VAL_MASK(immr->im_siu_conf.sc_bcr, CONFIG_SYS_BCR_60x, 0x80000010); +	} else { +		immr->im_siu_conf.sc_bcr = SET_VAL_MASK(immr->im_siu_conf.sc_bcr, CONFIG_SYS_BCR_SINGLE, 0x80000010); +	} +#else +	immr->im_siu_conf.sc_bcr = CONFIG_SYS_BCR; +#endif + +	/* SIUMCR - contains debug pin configuration (4-31) */ +#if defined(CONFIG_SYS_SIUMCR_LOW) && (CONFIG_SYS_SIUMCR_HIGH) +	cpu_clk = board_get_cpu_clk_f (); +	if (cpu_clk >= 100000000) { +		immr->im_siu_conf.sc_siumcr = SET_VAL_MASK(immr->im_siu_conf.sc_siumcr, CONFIG_SYS_SIUMCR_HIGH, 0x9f3cc000); +	} else { +		immr->im_siu_conf.sc_siumcr = SET_VAL_MASK(immr->im_siu_conf.sc_siumcr, CONFIG_SYS_SIUMCR_LOW, 0x9f3cc000); +	} +#else +	immr->im_siu_conf.sc_siumcr = CONFIG_SYS_SIUMCR; +#endif + +	config_8260_ioports (immr); + +	/* initialize time counter status and control register (4-40) */ +	immr->im_sit.sit_tmcntsc = CONFIG_SYS_TMCNTSC; + +	/* initialize the PIT (4-42) */ +	immr->im_sit.sit_piscr = CONFIG_SYS_PISCR; + +#if !defined(CONFIG_COGENT)		/* done in start.S for the cogent */ +	/* System clock control register (9-8) */ +	sccr = immr->im_clkrst.car_sccr & +		(SCCR_PCI_MODE | SCCR_PCI_MODCK | SCCR_PCIDF_MSK); +	immr->im_clkrst.car_sccr = sccr | +		(CONFIG_SYS_SCCR & ~(SCCR_PCI_MODE | SCCR_PCI_MODCK | SCCR_PCIDF_MSK) ); +#endif /* !CONFIG_COGENT */ + +	/* +	 * Memory Controller: +	 */ + +	/* Map banks 0 and 1 to the FLASH banks 0 and 1 at preliminary +	 * addresses - these have to be modified later when FLASH size +	 * has been determined +	 */ + +#if defined(CONFIG_SYS_OR0_REMAP) +	memctl->memc_or0 = CONFIG_SYS_OR0_REMAP; +#endif +#if defined(CONFIG_SYS_OR1_REMAP) +	memctl->memc_or1 = CONFIG_SYS_OR1_REMAP; +#endif + +	/* now restrict to preliminary range */ +	/* the PS came from the HRCW, donīt change it */ +	memctl->memc_br0 = SET_VAL_MASK(memctl->memc_br0 , CONFIG_SYS_BR0_PRELIM, BRx_PS_MSK); +	memctl->memc_or0 = CONFIG_SYS_OR0_PRELIM; + +#if defined(CONFIG_SYS_BR1_PRELIM) && defined(CONFIG_SYS_OR1_PRELIM) +	memctl->memc_or1 = CONFIG_SYS_OR1_PRELIM; +	memctl->memc_br1 = CONFIG_SYS_BR1_PRELIM; +#endif + +#if defined(CONFIG_SYS_BR2_PRELIM) && defined(CONFIG_SYS_OR2_PRELIM) +	memctl->memc_or2 = CONFIG_SYS_OR2_PRELIM; +	memctl->memc_br2 = CONFIG_SYS_BR2_PRELIM; +#endif + +#if defined(CONFIG_SYS_BR3_PRELIM) && defined(CONFIG_SYS_OR3_PRELIM) +	memctl->memc_or3 = CONFIG_SYS_OR3_PRELIM; +	memctl->memc_br3 = CONFIG_SYS_BR3_PRELIM; +#endif + +#if defined(CONFIG_SYS_BR4_PRELIM) && defined(CONFIG_SYS_OR4_PRELIM) +	memctl->memc_or4 = CONFIG_SYS_OR4_PRELIM; +	memctl->memc_br4 = CONFIG_SYS_BR4_PRELIM; +#endif + +#if defined(CONFIG_SYS_BR5_PRELIM) && defined(CONFIG_SYS_OR5_PRELIM) +	memctl->memc_or5 = CONFIG_SYS_OR5_PRELIM; +	memctl->memc_br5 = CONFIG_SYS_BR5_PRELIM; +#endif + +#if defined(CONFIG_SYS_BR6_PRELIM) && defined(CONFIG_SYS_OR6_PRELIM) +	memctl->memc_or6 = CONFIG_SYS_OR6_PRELIM; +	memctl->memc_br6 = CONFIG_SYS_BR6_PRELIM; +#endif + +#if defined(CONFIG_SYS_BR7_PRELIM) && defined(CONFIG_SYS_OR7_PRELIM) +	memctl->memc_or7 = CONFIG_SYS_OR7_PRELIM; +	memctl->memc_br7 = CONFIG_SYS_BR7_PRELIM; +#endif + +#if defined(CONFIG_SYS_BR8_PRELIM) && defined(CONFIG_SYS_OR8_PRELIM) +	memctl->memc_or8 = CONFIG_SYS_OR8_PRELIM; +	memctl->memc_br8 = CONFIG_SYS_BR8_PRELIM; +#endif + +#if defined(CONFIG_SYS_BR9_PRELIM) && defined(CONFIG_SYS_OR9_PRELIM) +	memctl->memc_or9 = CONFIG_SYS_OR9_PRELIM; +	memctl->memc_br9 = CONFIG_SYS_BR9_PRELIM; +#endif + +#if defined(CONFIG_SYS_BR10_PRELIM) && defined(CONFIG_SYS_OR10_PRELIM) +	memctl->memc_or10 = CONFIG_SYS_OR10_PRELIM; +	memctl->memc_br10 = CONFIG_SYS_BR10_PRELIM; +#endif + +#if defined(CONFIG_SYS_BR11_PRELIM) && defined(CONFIG_SYS_OR11_PRELIM) +	memctl->memc_or11 = CONFIG_SYS_OR11_PRELIM; +	memctl->memc_br11 = CONFIG_SYS_BR11_PRELIM; +#endif + +	m8260_cpm_reset (); +} + +/* + * initialize higher level parts of CPU like time base and timers + */ +int cpu_init_r (void) +{ +	volatile immap_t *immr = (immap_t *) gd->bd->bi_immr_base; + +	immr->im_cpm.cp_rccr = CONFIG_SYS_RCCR; + +	return (0); +} + +/* + * print out the reason for the reset + */ +int prt_8260_rsr (void) +{ +	static struct { +		ulong mask; +		char *desc; +	} bits[] = { +		{ +		RSR_JTRS, "JTAG"}, { +		RSR_CSRS, "Check Stop"}, { +		RSR_SWRS, "Software Watchdog"}, { +		RSR_BMRS, "Bus Monitor"}, { +		RSR_ESRS, "External Soft"}, { +		RSR_EHRS, "External Hard"} +	}; +	static int n = sizeof bits / sizeof bits[0]; +	ulong rsr = gd->reset_status; +	int i; +	char *sep; + +	puts (CPU_ID_STR " Reset Status:"); + +	sep = " "; +	for (i = 0; i < n; i++) +		if (rsr & bits[i].mask) { +			printf ("%s%s", sep, bits[i].desc); +			sep = ", "; +		} + +	puts ("\n\n"); +	return (0); +} |