diff options
| author | fishsoupisgood <github@madingley.org> | 2019-04-29 01:17:54 +0100 | 
|---|---|---|
| committer | fishsoupisgood <github@madingley.org> | 2019-05-27 03:43:43 +0100 | 
| commit | 3f2546b2ef55b661fd8dd69682b38992225e86f6 (patch) | |
| tree | 65ca85f13617aee1dce474596800950f266a456c /roms/u-boot/arch/powerpc/cpu/mpc512x | |
| download | qemu-master.tar.gz qemu-master.tar.bz2 qemu-master.zip  | |
Diffstat (limited to 'roms/u-boot/arch/powerpc/cpu/mpc512x')
18 files changed, 3029 insertions, 0 deletions
diff --git a/roms/u-boot/arch/powerpc/cpu/mpc512x/Makefile b/roms/u-boot/arch/powerpc/cpu/mpc512x/Makefile new file mode 100644 index 00000000..a4934ef7 --- /dev/null +++ b/roms/u-boot/arch/powerpc/cpu/mpc512x/Makefile @@ -0,0 +1,22 @@ +# +# (C) Copyright 2007-2009 DENX Software Engineering +# +# SPDX-License-Identifier:	GPL-2.0+ +# + +extra-y	= start.o +obj-y	:= cpu.o +obj-y	+= traps.o +obj-y += cpu_init.o +obj-y += fixed_sdram.o +obj-y += i2c.o +obj-y += interrupts.o +obj-y += iopin.o +obj-y += serial.o +obj-y += speed.o +obj-$(CONFIG_FSL_DIU_FB) += diu.o +obj-$(CONFIG_CMD_IDE) += ide.o +obj-$(CONFIG_PCI) += pci.o + +# Stub implementations of cache management functions for USB +obj-$(CONFIG_USB_EHCI) += cache.o diff --git a/roms/u-boot/arch/powerpc/cpu/mpc512x/asm-offsets.h b/roms/u-boot/arch/powerpc/cpu/mpc512x/asm-offsets.h new file mode 100644 index 00000000..957d4be2 --- /dev/null +++ b/roms/u-boot/arch/powerpc/cpu/mpc512x/asm-offsets.h @@ -0,0 +1,15 @@ +/* + * needed for arch/powerpc/cpu/mpc512x/start.S + * + * These should be auto-generated + */ +#define LPCS0AW			0x0024 +#define SRAMBAR			0x00C4 +#define SWCRR			0x0904 +#define LPC_OFFSET		0x10000 +#define CS0_CONFIG		0x00000 +#define CS_CTRL			0x00020 +#define CS_CTRL_ME		0x01000000	/* CS Master Enable bit */ + +#define EXC_OFF_SYS_RESET	0x0100 +#define	_START_OFFSET		EXC_OFF_SYS_RESET diff --git a/roms/u-boot/arch/powerpc/cpu/mpc512x/cache.c b/roms/u-boot/arch/powerpc/cpu/mpc512x/cache.c new file mode 100644 index 00000000..66384f98 --- /dev/null +++ b/roms/u-boot/arch/powerpc/cpu/mpc512x/cache.c @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2012 Marek Vasut <marex@denx.de> + * + * This file contains stub implementation of + *   invalidate_dcache_range() + *   flush_dcache_range() + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +void invalidate_dcache_range(unsigned long start, unsigned long stop) +{ +} + +void flush_dcache_range(unsigned long start, unsigned long stop) +{ +} diff --git a/roms/u-boot/arch/powerpc/cpu/mpc512x/config.mk b/roms/u-boot/arch/powerpc/cpu/mpc512x/config.mk new file mode 100644 index 00000000..03759e66 --- /dev/null +++ b/roms/u-boot/arch/powerpc/cpu/mpc512x/config.mk @@ -0,0 +1,7 @@ +# +# (C) Copyright 2007-2010 DENX Software Engineering +# +# SPDX-License-Identifier:	GPL-2.0+ +# + +PLATFORM_CPPFLAGS += -DCONFIG_MPC512X -DCONFIG_E300 -msoft-float -mcpu=603e diff --git a/roms/u-boot/arch/powerpc/cpu/mpc512x/cpu.c b/roms/u-boot/arch/powerpc/cpu/mpc512x/cpu.c new file mode 100644 index 00000000..8508e8db --- /dev/null +++ b/roms/u-boot/arch/powerpc/cpu/mpc512x/cpu.c @@ -0,0 +1,200 @@ +/* + * (C) Copyright 2007-2010 DENX Software Engineering + * Copyright (C) 2004-2006 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +/* + * CPU specific code for the MPC512x family. + * + * Derived from the MPC83xx code. + */ + +#include <common.h> +#include <command.h> +#include <net.h> +#include <netdev.h> +#include <asm/processor.h> +#include <asm/io.h> + +#if defined(CONFIG_OF_LIBFDT) +#include <fdt_support.h> +#endif + +DECLARE_GLOBAL_DATA_PTR; + +int checkcpu (void) +{ +	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR; +	ulong clock = gd->cpu_clk; +	u32 pvr = get_pvr (); +	u32 spridr = in_be32(&immr->sysconf.spridr); +	char buf1[32], buf2[32]; + +	puts ("CPU:   "); + +	switch (spridr & 0xffff0000) { +	case SPR_5121E: +		puts ("MPC5121e "); +		break; +	default: +		printf ("Unknown part ID %08x ", spridr & 0xffff0000); +	} +	printf ("rev. %d.%d, Core ", SVR_MJREV (spridr), SVR_MNREV (spridr)); + +	switch (pvr & 0xffff0000) { +	case PVR_E300C4: +		puts ("e300c4 "); +		break; +	default: +		puts ("unknown "); +	} +	printf ("at %s MHz, CSB at %s MHz (RSR=0x%04lx)\n", +		strmhz(buf1, clock), +		strmhz(buf2, gd->arch.csb_clk), +		gd->arch.reset_status & 0xffff); +	return 0; +} + + +int +do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) +{ +	ulong msr; +	volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; + +	/* Interrupts and MMU off */ +	__asm__ __volatile__ ("mfmsr    %0":"=r" (msr):); + +	msr &= ~( MSR_EE | MSR_IR | MSR_DR); +	__asm__ __volatile__ ("mtmsr    %0"::"r" (msr)); + +	/* +	 * Enable Reset Control Reg - "RSTE" is the magic word that let us go +	 */ +	out_be32(&immap->reset.rpr, 0x52535445); + +	/* Verify Reset Control Reg is enabled */ +	while (!(in_be32(&immap->reset.rcer) & RCER_CRE)) +		; + +	printf ("Resetting the board.\n"); +	udelay(200); + +	/* Perform reset */ +	out_be32(&immap->reset.rcr, RCR_SWHR); + +	/* Unreached... */ +	return 1; +} + + +/* + * Get timebase clock frequency (like cpu_clk in Hz) + */ +unsigned long get_tbclk (void) +{ +	ulong tbclk; + +	tbclk = (gd->bus_clk + 3L) / 4L; + +	return tbclk; +} + + +#if defined(CONFIG_WATCHDOG) +void watchdog_reset (void) +{ +	int re_enable = disable_interrupts (); + +	/* Reset watchdog */ +	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR; +	out_be32(&immr->wdt.swsrr, 0x556c); +	out_be32(&immr->wdt.swsrr, 0xaa39); + +	if (re_enable) +		enable_interrupts (); +} +#endif + +#ifdef CONFIG_OF_LIBFDT + +#ifdef CONFIG_OF_SUPPORT_OLD_DEVICE_TREES +/* + * fdt setup for old device trees + * fix up + * 	cpu clocks + * 	soc clocks + * 	ethernet addresses + */ +static void old_ft_cpu_setup(void *blob, bd_t *bd) +{ +	/* +	 * avoid fixing up by path because that +	 * produces scary error messages +	 */ +	uchar enetaddr[6]; + +	/* +	 * old device trees have ethernet nodes with +	 * device_type = "network" +	 */ +	eth_getenv_enetaddr("ethaddr", enetaddr); +	do_fixup_by_prop(blob, "device_type", "network", 8, +		"local-mac-address", enetaddr, 6, 0); +	do_fixup_by_prop(blob, "device_type", "network", 8, +		"address", enetaddr, 6, 0); +	/* +	 * old device trees have soc nodes with +	 * device_type = "soc" +	 */ +	do_fixup_by_prop_u32(blob, "device_type", "soc", 4, +		"bus-frequency", bd->bi_ipsfreq, 0); +} +#endif + +static void ft_clock_setup(void *blob, bd_t *bd) +{ +	char *cpu_path = "/cpus/" OF_CPU; + +	/* +	 * fixup cpu clocks using path +	 */ +	do_fixup_by_path_u32(blob, cpu_path, +		"timebase-frequency", OF_TBCLK, 1); +	do_fixup_by_path_u32(blob, cpu_path, +		"bus-frequency", bd->bi_busfreq, 1); +	do_fixup_by_path_u32(blob, cpu_path, +		"clock-frequency", bd->bi_intfreq, 1); +	/* +	 * fixup soc clocks using compatible +	 */ +	do_fixup_by_compat_u32(blob, OF_SOC_COMPAT, +		"bus-frequency", bd->bi_ipsfreq, 1); +} + +void ft_cpu_setup(void *blob, bd_t *bd) +{ +#ifdef CONFIG_OF_SUPPORT_OLD_DEVICE_TREES +	old_ft_cpu_setup(blob, bd); +#endif +	ft_clock_setup(blob, bd); +#ifdef CONFIG_HAS_ETH0 +	fdt_fixup_ethernet(blob); +#endif +	fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize); +} +#endif + +#ifdef CONFIG_MPC512x_FEC +/* Default initializations for FEC controllers.  To override, + * create a board-specific function called: + * 	int board_eth_init(bd_t *bis) + */ + +int cpu_eth_init(bd_t *bis) +{ +	return mpc512x_fec_initialize(bis); +} +#endif diff --git a/roms/u-boot/arch/powerpc/cpu/mpc512x/cpu_init.c b/roms/u-boot/arch/powerpc/cpu/mpc512x/cpu_init.c new file mode 100644 index 00000000..48a5e4f8 --- /dev/null +++ b/roms/u-boot/arch/powerpc/cpu/mpc512x/cpu_init.c @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2004-2006 Freescale Semiconductor, Inc. + * Copyright (C) 2007-2009 DENX Software Engineering + * + * SPDX-License-Identifier:	GPL-2.0+ + * + * Derived from the MPC83xx code. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/mpc512x.h> +#include <asm/processor.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* + * Set up the memory map, initialize registers, + */ +void cpu_init_f (volatile immap_t * im) +{ +	u32 ips_div; + +	/* 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)); + +	/* Local Window and chip select configuration */ +#if defined(CONFIG_SYS_CS0_START) && defined(CONFIG_SYS_CS0_SIZE) +	out_be32(&im->sysconf.lpcs0aw, +		CSAW_START(CONFIG_SYS_CS0_START) | +		CSAW_STOP(CONFIG_SYS_CS0_START, CONFIG_SYS_CS0_SIZE)); +	sync_law(&im->sysconf.lpcs0aw); +#endif +#if defined(CONFIG_SYS_CS0_CFG) +	out_be32(&im->lpc.cs_cfg[0], CONFIG_SYS_CS0_CFG); +#endif + +#if defined(CONFIG_SYS_CS1_START) && defined(CONFIG_SYS_CS1_SIZE) +	out_be32(&im->sysconf.lpcs1aw, +		CSAW_START(CONFIG_SYS_CS1_START) | +		CSAW_STOP(CONFIG_SYS_CS1_START, CONFIG_SYS_CS1_SIZE)); +	sync_law(&im->sysconf.lpcs1aw); +#endif +#if defined(CONFIG_SYS_CS1_CFG) +	out_be32(&im->lpc.cs_cfg[1], CONFIG_SYS_CS1_CFG); +#endif + +#if defined(CONFIG_SYS_CS2_START) && (defined CONFIG_SYS_CS2_SIZE) +	out_be32(&im->sysconf.lpcs2aw, +		CSAW_START(CONFIG_SYS_CS2_START) | +		CSAW_STOP(CONFIG_SYS_CS2_START, CONFIG_SYS_CS2_SIZE)); +	sync_law(&im->sysconf.lpcs2aw); +#endif +#if defined(CONFIG_SYS_CS2_CFG) +	out_be32(&im->lpc.cs_cfg[2], CONFIG_SYS_CS2_CFG); +#endif + +#if defined(CONFIG_SYS_CS3_START) && defined(CONFIG_SYS_CS3_SIZE) +	out_be32(&im->sysconf.lpcs3aw, +		CSAW_START(CONFIG_SYS_CS3_START) | +		CSAW_STOP(CONFIG_SYS_CS3_START, CONFIG_SYS_CS3_SIZE)); +	sync_law(&im->sysconf.lpcs3aw); +#endif +#if defined(CONFIG_SYS_CS3_CFG) +	out_be32(&im->lpc.cs_cfg[3], CONFIG_SYS_CS3_CFG); +#endif + +#if defined(CONFIG_SYS_CS4_START) && defined(CONFIG_SYS_CS4_SIZE) +	out_be32(&im->sysconf.lpcs4aw, +		CSAW_START(CONFIG_SYS_CS4_START) | +		CSAW_STOP(CONFIG_SYS_CS4_START, CONFIG_SYS_CS4_SIZE)); +	sync_law(&im->sysconf.lpcs4aw); +#endif +#if defined(CONFIG_SYS_CS4_CFG) +	out_be32(&im->lpc.cs_cfg[4], CONFIG_SYS_CS4_CFG); +#endif + +#if defined(CONFIG_SYS_CS5_START) && defined(CONFIG_SYS_CS5_SIZE) +	out_be32(&im->sysconf.lpcs5aw, +		CSAW_START(CONFIG_SYS_CS5_START) | +		CSAW_STOP(CONFIG_SYS_CS5_START, CONFIG_SYS_CS5_SIZE)); +	sync_law(&im->sysconf.lpcs5aw); +#endif +#if defined(CONFIG_SYS_CS5_CFG) +	out_be32(&im->lpc.cs_cfg[5], CONFIG_SYS_CS5_CFG); +#endif + +#if defined(CONFIG_SYS_CS6_START) && defined(CONFIG_SYS_CS6_SIZE) +	out_be32(&im->sysconf.lpcs6aw, +		CSAW_START(CONFIG_SYS_CS6_START) | +		CSAW_STOP(CONFIG_SYS_CS6_START, CONFIG_SYS_CS6_SIZE)); +	sync_law(&im->sysconf.lpcs6aw); +#endif +#if defined(CONFIG_SYS_CS6_CFG) +	out_be32(&im->lpc.cs_cfg[6], CONFIG_SYS_CS6_CFG); +#endif + +#if defined(CONFIG_SYS_CS7_START) && defined(CONFIG_SYS_CS7_SIZE) +	out_be32(&im->sysconf.lpcs7aw, +		CSAW_START(CONFIG_SYS_CS7_START) | +		CSAW_STOP(CONFIG_SYS_CS7_START, CONFIG_SYS_CS7_SIZE)); +	sync_law(&im->sysconf.lpcs7aw); +#endif +#if defined(CONFIG_SYS_CS7_CFG) +	out_be32(&im->lpc.cs_cfg[7], CONFIG_SYS_CS7_CFG); +#endif + +#if defined CONFIG_SYS_CS_ALETIMING +	if (SVR_MJREV(in_be32(&im->sysconf.spridr)) >= 2) +		out_be32(&im->lpc.altr, CONFIG_SYS_CS_ALETIMING); +#endif +#if defined CONFIG_SYS_CS_BURST +	out_be32(&im->lpc.cs_bcr, CONFIG_SYS_CS_BURST); +#endif +#if defined CONFIG_SYS_CS_DEADCYCLE +	out_be32(&im->lpc.cs_dccr, CONFIG_SYS_CS_DEADCYCLE); +#endif +#if defined CONFIG_SYS_CS_HOLDCYCLE +	out_be32(&im->lpc.cs_hccr, CONFIG_SYS_CS_HOLDCYCLE); +#endif + +	/* system performance tweaking */ + +#ifdef CONFIG_SYS_ACR_PIPE_DEP +	/* Arbiter pipeline depth */ +	out_be32(&im->arbiter.acr, +		(im->arbiter.acr & ~ACR_PIPE_DEP) | +		(CONFIG_SYS_ACR_PIPE_DEP << ACR_PIPE_DEP_SHIFT) +	); +#endif + +#ifdef CONFIG_SYS_ACR_RPTCNT +	/* Arbiter repeat count */ +	out_be32(im->arbiter.acr, +		(im->arbiter.acr & ~(ACR_RPTCNT)) | +		(CONFIG_SYS_ACR_RPTCNT << ACR_RPTCNT_SHIFT) +	); +#endif + +	/* RSR - Reset Status Register - clear all status */ +	gd->arch.reset_status = im->reset.rsr; +	out_be32(&im->reset.rsr, ~RSR_RES); + +	/* +	 * RMR - Reset Mode Register - enable checkstop reset +	 */ +	out_be32(&im->reset.rmr, RMR_CSRE & (1 << RMR_CSRE_SHIFT)); + +	/* Set IPS-CSB divider: IPS = 1/2 CSB */ +	ips_div = in_be32(&im->clk.scfr[0]); +	ips_div &= ~(SCFR1_IPS_DIV_MASK); +	ips_div |= SCFR1_IPS_DIV << SCFR1_IPS_DIV_SHIFT; +	out_be32(&im->clk.scfr[0], ips_div); + +#ifdef SCFR1_LPC_DIV +	clrsetbits_be32(&im->clk.scfr[0], SCFR1_LPC_DIV_MASK, +			SCFR1_LPC_DIV << SCFR1_LPC_DIV_SHIFT); +#endif + +#ifdef SCFR1_NFC_DIV +	clrsetbits_be32(&im->clk.scfr[0], SCFR1_NFC_DIV_MASK, +			SCFR1_NFC_DIV << SCFR1_NFC_DIV_SHIFT); +#endif + +#ifdef SCFR1_DIU_DIV +	clrsetbits_be32(&im->clk.scfr[0], SCFR1_DIU_DIV_MASK, +			SCFR1_DIU_DIV << SCFR1_DIU_DIV_SHIFT); +#endif + +	/* +	 * Enable Time Base/Decrementer +	 * +	 * NOTICE: TB needs to be enabled as early as possible in order to +	 * have udelay() working; if not enabled, usually leads to a hang, like +	 * during FLASH chip identification etc. +	 */ +	setbits_be32(&im->sysconf.spcr, SPCR_TBEN); + +	/* +	 * Enable clocks +	 */ +	out_be32(&im->clk.sccr[0], SCCR1_CLOCKS_EN); +	out_be32(&im->clk.sccr[1], SCCR2_CLOCKS_EN); +#if defined(CONFIG_FSL_IIM) || defined(CONFIG_CMD_FUSE) +	setbits_be32(&im->clk.sccr[1], CLOCK_SCCR2_IIM_EN); +#endif +} + +int cpu_init_r (void) +{ +	return 0; +} diff --git a/roms/u-boot/arch/powerpc/cpu/mpc512x/diu.c b/roms/u-boot/arch/powerpc/cpu/mpc512x/diu.c new file mode 100644 index 00000000..36e1f9cf --- /dev/null +++ b/roms/u-boot/arch/powerpc/cpu/mpc512x/diu.c @@ -0,0 +1,44 @@ +/* + * Copyright 2008 Freescale Semiconductor, Inc. + * York Sun <yorksun@freescale.com> + * + * FSL DIU Framebuffer driver + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <command.h> +#include <asm/io.h> + +#include <fsl_diu_fb.h> + +DECLARE_GLOBAL_DATA_PTR; + +void diu_set_pixel_clock(unsigned int pixclock) +{ +	volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR; +	volatile clk512x_t *clk = &immap->clk; +	volatile unsigned int *clkdvdr = &clk->scfr[0]; +	unsigned long speed_ccb, temp, pixval; + +	speed_ccb = get_bus_freq(0) * 4; +	temp = 1000000000/pixclock; +	temp *= 1000; +	pixval = speed_ccb / temp; +	debug("DIU pixval = %lu\n", pixval); + +	/* Modify PXCLK in GUTS CLKDVDR */ +	debug("DIU: Current value of CLKDVDR = 0x%08x\n", in_be32(clkdvdr)); +	temp = in_be32(clkdvdr) & 0xFFFFFF00; +	out_be32(clkdvdr, temp | (pixval & 0xFF)); +	debug("DIU: Modified value of CLKDVDR = 0x%08x\n", in_be32(clkdvdr)); +} + +int platform_diu_init(unsigned int xres, unsigned int yres, const char *port) +{ +	unsigned int pixel_format = 0x88883316; + +	debug("mpc5121_diu_init\n"); +	return fsl_diu_init(xres, yres, pixel_format, 0); +} diff --git a/roms/u-boot/arch/powerpc/cpu/mpc512x/fixed_sdram.c b/roms/u-boot/arch/powerpc/cpu/mpc512x/fixed_sdram.c new file mode 100644 index 00000000..6451ea9a --- /dev/null +++ b/roms/u-boot/arch/powerpc/cpu/mpc512x/fixed_sdram.c @@ -0,0 +1,155 @@ +/* + * (C) Copyright 2007-2009 DENX Software Engineering + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/mpc512x.h> + +/* + * MDDRC Config Runtime Settings + */ +ddr512x_config_t default_mddrc_config = { +	.ddr_sys_config   = CONFIG_SYS_MDDRC_SYS_CFG, +	.ddr_time_config0 = CONFIG_SYS_MDDRC_TIME_CFG0, +	.ddr_time_config1 = CONFIG_SYS_MDDRC_TIME_CFG1, +	.ddr_time_config2 = CONFIG_SYS_MDDRC_TIME_CFG2, +}; + +u32 default_init_seq[] = { +	CONFIG_SYS_DDRCMD_NOP, +	CONFIG_SYS_DDRCMD_NOP, +	CONFIG_SYS_DDRCMD_NOP, +	CONFIG_SYS_DDRCMD_NOP, +	CONFIG_SYS_DDRCMD_NOP, +	CONFIG_SYS_DDRCMD_NOP, +	CONFIG_SYS_DDRCMD_NOP, +	CONFIG_SYS_DDRCMD_NOP, +	CONFIG_SYS_DDRCMD_NOP, +	CONFIG_SYS_DDRCMD_NOP, +	CONFIG_SYS_DDRCMD_PCHG_ALL, +	CONFIG_SYS_DDRCMD_NOP, +	CONFIG_SYS_DDRCMD_RFSH, +	CONFIG_SYS_DDRCMD_NOP, +	CONFIG_SYS_DDRCMD_RFSH, +	CONFIG_SYS_DDRCMD_NOP, +	CONFIG_SYS_MICRON_INIT_DEV_OP, +	CONFIG_SYS_DDRCMD_NOP, +	CONFIG_SYS_DDRCMD_EM2, +	CONFIG_SYS_DDRCMD_NOP, +	CONFIG_SYS_DDRCMD_PCHG_ALL, +	CONFIG_SYS_DDRCMD_EM2, +	CONFIG_SYS_DDRCMD_EM3, +	CONFIG_SYS_DDRCMD_EN_DLL, +	CONFIG_SYS_MICRON_INIT_DEV_OP, +	CONFIG_SYS_DDRCMD_PCHG_ALL, +	CONFIG_SYS_DDRCMD_RFSH, +	CONFIG_SYS_MICRON_INIT_DEV_OP, +	CONFIG_SYS_DDRCMD_OCD_DEFAULT, +	CONFIG_SYS_DDRCMD_PCHG_ALL, +	CONFIG_SYS_DDRCMD_NOP +}; + +/* + * fixed sdram init: + * The board doesn't use memory modules that have serial presence + * detect or similar mechanism for discovery of the DRAM settings + */ +long int fixed_sdram(ddr512x_config_t *mddrc_config, +			u32 *dram_init_seq, int seq_sz) +{ +	volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR; +	u32 msize = CONFIG_SYS_MAX_RAM_SIZE; +	u32 msize_log2 = __ilog2(msize); +	u32 i; + +	/* take default settings and init sequence if necessary */ +	if (mddrc_config == NULL) +		mddrc_config = &default_mddrc_config; +	if (dram_init_seq == NULL) { +		dram_init_seq = default_init_seq; +		seq_sz = sizeof(default_init_seq)/sizeof(u32); +	} + +	/* Initialize IO Control */ +	out_be32(&im->io_ctrl.io_control_mem, CONFIG_SYS_IOCTRL_MUX_DDR); + +	/* Initialize DDR Local Window */ +	out_be32(&im->sysconf.ddrlaw.bar, CONFIG_SYS_DDR_BASE & 0xFFFFF000); +	out_be32(&im->sysconf.ddrlaw.ar, msize_log2 - 1); +	sync_law(&im->sysconf.ddrlaw.ar); + +	/* DDR Enable */ +	/* +	 * the "enable" combination: DRAM controller out of reset, +	 * clock enabled, command mode -- BUT leave CKE low for now +	 */ +	i = MDDRC_SYS_CFG_EN & ~MDDRC_SYS_CFG_CKE_MASK; +	out_be32(&im->mddrc.ddr_sys_config, i); +	/* maintain 200 microseconds of stable power and clock */ +	udelay(200); +	/* apply a NOP, it shouldn't harm */ +	out_be32(&im->mddrc.ddr_command, CONFIG_SYS_DDRCMD_NOP); +	/* now assert CKE (high) */ +	i |= MDDRC_SYS_CFG_CKE_MASK; +	out_be32(&im->mddrc.ddr_sys_config, i); + +	/* Initialize DDR Priority Manager */ +	out_be32(&im->mddrc.prioman_config1, CONFIG_SYS_MDDRCGRP_PM_CFG1); +	out_be32(&im->mddrc.prioman_config2, CONFIG_SYS_MDDRCGRP_PM_CFG2); +	out_be32(&im->mddrc.hiprio_config, CONFIG_SYS_MDDRCGRP_HIPRIO_CFG); +	out_be32(&im->mddrc.lut_table0_main_upper, CONFIG_SYS_MDDRCGRP_LUT0_MU); +	out_be32(&im->mddrc.lut_table0_main_lower, CONFIG_SYS_MDDRCGRP_LUT0_ML); +	out_be32(&im->mddrc.lut_table1_main_upper, CONFIG_SYS_MDDRCGRP_LUT1_MU); +	out_be32(&im->mddrc.lut_table1_main_lower, CONFIG_SYS_MDDRCGRP_LUT1_ML); +	out_be32(&im->mddrc.lut_table2_main_upper, CONFIG_SYS_MDDRCGRP_LUT2_MU); +	out_be32(&im->mddrc.lut_table2_main_lower, CONFIG_SYS_MDDRCGRP_LUT2_ML); +	out_be32(&im->mddrc.lut_table3_main_upper, CONFIG_SYS_MDDRCGRP_LUT3_MU); +	out_be32(&im->mddrc.lut_table3_main_lower, CONFIG_SYS_MDDRCGRP_LUT3_ML); +	out_be32(&im->mddrc.lut_table4_main_upper, CONFIG_SYS_MDDRCGRP_LUT4_MU); +	out_be32(&im->mddrc.lut_table4_main_lower, CONFIG_SYS_MDDRCGRP_LUT4_ML); +	out_be32(&im->mddrc.lut_table0_alternate_upper, CONFIG_SYS_MDDRCGRP_LUT0_AU); +	out_be32(&im->mddrc.lut_table0_alternate_lower, CONFIG_SYS_MDDRCGRP_LUT0_AL); +	out_be32(&im->mddrc.lut_table1_alternate_upper, CONFIG_SYS_MDDRCGRP_LUT1_AU); +	out_be32(&im->mddrc.lut_table1_alternate_lower, CONFIG_SYS_MDDRCGRP_LUT1_AL); +	out_be32(&im->mddrc.lut_table2_alternate_upper, CONFIG_SYS_MDDRCGRP_LUT2_AU); +	out_be32(&im->mddrc.lut_table2_alternate_lower, CONFIG_SYS_MDDRCGRP_LUT2_AL); +	out_be32(&im->mddrc.lut_table3_alternate_upper, CONFIG_SYS_MDDRCGRP_LUT3_AU); +	out_be32(&im->mddrc.lut_table3_alternate_lower, CONFIG_SYS_MDDRCGRP_LUT3_AL); +	out_be32(&im->mddrc.lut_table4_alternate_upper, CONFIG_SYS_MDDRCGRP_LUT4_AU); +	out_be32(&im->mddrc.lut_table4_alternate_lower, CONFIG_SYS_MDDRCGRP_LUT4_AL); + +	/* +	 * Initialize MDDRC +	 *  put MDDRC in CMD mode and +	 *  set the max time between refreshes to 0 during init process +	 */ +	out_be32(&im->mddrc.ddr_sys_config, +		mddrc_config->ddr_sys_config | MDDRC_SYS_CFG_CMD_MASK); +	out_be32(&im->mddrc.ddr_time_config0, +		mddrc_config->ddr_time_config0 & MDDRC_REFRESH_ZERO_MASK); +	out_be32(&im->mddrc.ddr_time_config1, +		mddrc_config->ddr_time_config1); +	out_be32(&im->mddrc.ddr_time_config2, +		mddrc_config->ddr_time_config2); + +	/* Initialize DDR with either default or supplied init sequence */ +	for (i = 0; i < seq_sz; i++) +		out_be32(&im->mddrc.ddr_command, dram_init_seq[i]); + +	/* Start MDDRC */ +	out_be32(&im->mddrc.ddr_time_config0, mddrc_config->ddr_time_config0); +	out_be32(&im->mddrc.ddr_sys_config, mddrc_config->ddr_sys_config); + +	/* Allow for the DLL to startup before accessing data */ +	udelay(10); + +	msize = get_ram_size(CONFIG_SYS_DDR_BASE, CONFIG_SYS_MAX_RAM_SIZE); +	/* Fix DDR Local Window for new size */ +	out_be32(&im->sysconf.ddrlaw.ar, __ilog2(msize) - 1); +	sync_law(&im->sysconf.ddrlaw.ar); + +	return msize; +} diff --git a/roms/u-boot/arch/powerpc/cpu/mpc512x/i2c.c b/roms/u-boot/arch/powerpc/cpu/mpc512x/i2c.c new file mode 100644 index 00000000..15d519a1 --- /dev/null +++ b/roms/u-boot/arch/powerpc/cpu/mpc512x/i2c.c @@ -0,0 +1,386 @@ +/* + * (C) Copyright 2003 - 2009 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + * + * Based on the MPC5xxx code. + */ + +#include <common.h> +#include <asm/io.h> + +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_HARD_I2C + +#include <i2c.h> + +/* by default set I2C bus 0 active */ +static unsigned int bus_num __attribute__ ((section (".data"))) = 0; + +#define I2C_TIMEOUT	100 +#define I2C_RETRIES	3 + +struct mpc512x_i2c_tap { +	int scl2tap; +	int tap2tap; +}; + +static int  mpc_reg_in(volatile u32 *reg); +static void mpc_reg_out(volatile u32 *reg, int val, int mask); +static int  wait_for_bb(void); +static int  wait_for_pin(int *status); +static int  do_address(uchar chip, char rdwr_flag); +static int  send_bytes(uchar chip, char *buf, int len); +static int  receive_bytes(uchar chip, char *buf, int len); +static int  mpc_get_fdr(int); + +static int mpc_reg_in (volatile u32 *reg) +{ +	int ret = in_be32(reg) >> 24; + +	return ret; +} + +static void mpc_reg_out (volatile u32 *reg, int val, int mask) +{ +	if (!mask) { +		out_be32(reg, val << 24); +	} else { +		clrsetbits_be32(reg, mask << 24, (val & mask) << 24); +	} +} + +static int wait_for_bb (void) +{ +	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; +	volatile i2c512x_dev_t *regs = &im->i2c.dev[bus_num]; +	int timeout = I2C_TIMEOUT; +	int status; + +	status = mpc_reg_in (®s->msr); + +	while (timeout-- && (status & I2C_BB)) { +		mpc_reg_out (®s->mcr, I2C_STA, I2C_STA); +		(void)mpc_reg_in(®s->mdr); +		mpc_reg_out (®s->mcr, 0, I2C_STA); +		mpc_reg_out (®s->mcr, 0, 0); +		mpc_reg_out (®s->mcr, I2C_EN, 0); + +		udelay (1000); +		status = mpc_reg_in (®s->msr); +	} + +	return (status & I2C_BB); +} + +static int wait_for_pin (int *status) +{ +	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; +	volatile i2c512x_dev_t *regs = &im->i2c.dev[bus_num]; +	int timeout = I2C_TIMEOUT; + +	*status = mpc_reg_in (®s->msr); + +	while (timeout-- && !(*status & I2C_IF)) { +		udelay (1000); +		*status = mpc_reg_in (®s->msr); +	} + +	if (!(*status & I2C_IF)) { +		return -1; +	} + +	mpc_reg_out (®s->msr, 0, I2C_IF); + +	return 0; +} + +static int do_address (uchar chip, char rdwr_flag) +{ +	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; +	volatile i2c512x_dev_t *regs = &im->i2c.dev[bus_num]; +	int status; + +	chip <<= 1; + +	if (rdwr_flag) { +		chip |= 1; +	} + +	mpc_reg_out (®s->mcr, I2C_TX, I2C_TX); +	mpc_reg_out (®s->mdr, chip, 0); + +	if (wait_for_pin (&status)) { +		return -2; +	} + +	if (status & I2C_RXAK) { +		return -3; +	} + +	return 0; +} + +static int send_bytes (uchar chip, char *buf, int len) +{ +	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; +	volatile i2c512x_dev_t *regs = &im->i2c.dev[bus_num]; +	int wrcount; +	int status; + +	for (wrcount = 0; wrcount < len; ++wrcount) { + +		mpc_reg_out (®s->mdr, buf[wrcount], 0); + +		if (wait_for_pin (&status)) { +			break; +		} + +		if (status & I2C_RXAK) { +			break; +		} + +	} + +	return !(wrcount == len); +} + +static int receive_bytes (uchar chip, char *buf, int len) +{ +	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; +	volatile i2c512x_dev_t *regs = &im->i2c.dev[bus_num]; +	int dummy   = 1; +	int rdcount = 0; +	int status; +	int i; + +	mpc_reg_out (®s->mcr, 0, I2C_TX); + +	for (i = 0; i < len; ++i) { +		buf[rdcount] = mpc_reg_in (®s->mdr); + +		if (dummy) { +			dummy = 0; +		} else { +			rdcount++; +		} + +		if (wait_for_pin (&status)) { +			return -4; +		} +	} + +	mpc_reg_out (®s->mcr, I2C_TXAK, I2C_TXAK); +	buf[rdcount++] = mpc_reg_in (®s->mdr); + +	if (wait_for_pin (&status)) { +		return -5; +	} + +	mpc_reg_out (®s->mcr, 0, I2C_TXAK); + +	return 0; +} + +/**************** I2C API ****************/ + +void i2c_init (int speed, int saddr) +{ +	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; +	int i; + +	for (i = 0; i < I2C_BUS_CNT; i++){ +		volatile i2c512x_dev_t *regs = &im->i2c.dev[i]; + +		mpc_reg_out (®s->mcr, 0, 0); + +		/* Set clock */ +		mpc_reg_out (®s->mfdr, mpc_get_fdr (speed), 0); +		mpc_reg_out (®s->madr, saddr << 1, 0); + +		/* Enable module */ +		mpc_reg_out (®s->mcr, I2C_EN, I2C_INIT_MASK); +		mpc_reg_out (®s->msr, 0, I2C_IF); +	} + +	/* Disable interrupts */ +	out_be32(&im->i2c.icr, 0); + +	/* Turn off filters */ +	out_be32(&im->i2c.mifr, 0); +} + +static int mpc_get_fdr (int speed) +{ +	static int fdr = -1; + +	if (fdr == -1) { +		ulong best_speed = 0; +		ulong divider; +		ulong ips, scl; +		ulong bestmatch = 0xffffffffUL; +		int best_i = 0, best_j = 0, i, j; +		int SCL_Tap[] = { 9, 10, 12, 15, 5, 6, 7, 8}; +		struct mpc512x_i2c_tap scltap[] = { +			{4, 1}, +			{4, 2}, +			{6, 4}, +			{6, 8}, +			{14, 16}, +			{30, 32}, +			{62, 64}, +			{126, 128} +		}; + +		ips = gd->arch.ips_clk; +		for (i = 7; i >= 0; i--) { +			for (j = 7; j >= 0; j--) { +				scl = 2 * (scltap[j].scl2tap + +					   (SCL_Tap[i] - 1) * scltap[j].tap2tap +					   + 2); +				if (ips <= speed*scl) { +					if ((speed*scl - ips) < bestmatch) { +						bestmatch = speed*scl - ips; +						best_i = i; +						best_j = j; +						best_speed = ips/scl; +					} +				} +			} +		} +		divider = (best_i & 3) | ((best_i & 4) << 3) | (best_j << 2); +		if (gd->flags & GD_FLG_RELOC) { +			fdr = divider; +		} else { +			debug("%ld kHz, \n", best_speed / 1000); +			return divider; +		} +	} + +	return fdr; +} + +int i2c_probe (uchar chip) +{ +	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; +	volatile i2c512x_dev_t *regs = &im->i2c.dev[bus_num]; +	int i; + +	for (i = 0; i < I2C_RETRIES; i++) { +		mpc_reg_out (®s->mcr, I2C_STA, I2C_STA); + +		if (! do_address (chip, 0)) { +			mpc_reg_out (®s->mcr, 0, I2C_STA); +			udelay (500); +			break; +		} + +		mpc_reg_out (®s->mcr, 0, I2C_STA); +		udelay (500); +	} + +	return (i == I2C_RETRIES); +} + +int i2c_read (uchar chip, uint addr, int alen, uchar *buf, int len) +{ +	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; +	volatile i2c512x_dev_t *regs = &im->i2c.dev[bus_num]; +	char xaddr[4]; +	int ret = -1; + +	xaddr[0] = (addr >> 24) & 0xFF; +	xaddr[1] = (addr >> 16) & 0xFF; +	xaddr[2] = (addr >>  8) & 0xFF; +	xaddr[3] =  addr	& 0xFF; + +	if (wait_for_bb ()) { +		printf ("i2c_read: bus is busy\n"); +		goto Done; +	} + +	mpc_reg_out (®s->mcr, I2C_STA, I2C_STA); +	if (do_address (chip, 0)) { +		printf ("i2c_read: failed to address chip\n"); +		goto Done; +	} + +	if (send_bytes (chip, &xaddr[4-alen], alen)) { +		printf ("i2c_read: send_bytes failed\n"); +		goto Done; +	} + +	mpc_reg_out (®s->mcr, I2C_RSTA, I2C_RSTA); +	if (do_address (chip, 1)) { +		printf ("i2c_read: failed to address chip\n"); +		goto Done; +	} + +	if (receive_bytes (chip, (char *)buf, len)) { +		printf ("i2c_read: receive_bytes failed\n"); +		goto Done; +	} + +	ret = 0; +Done: +	mpc_reg_out (®s->mcr, 0, I2C_STA); +	return ret; +} + +int i2c_write (uchar chip, uint addr, int alen, uchar *buf, int len) +{ +	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; +	volatile i2c512x_dev_t *regs = &im->i2c.dev[bus_num]; +	char xaddr[4]; +	int ret = -1; + +	xaddr[0] = (addr >> 24) & 0xFF; +	xaddr[1] = (addr >> 16) & 0xFF; +	xaddr[2] = (addr >>  8) & 0xFF; +	xaddr[3] =  addr	& 0xFF; + +	if (wait_for_bb ()) { +		printf ("i2c_write: bus is busy\n"); +		goto Done; +	} + +	mpc_reg_out (®s->mcr, I2C_STA, I2C_STA); +	if (do_address (chip, 0)) { +		printf ("i2c_write: failed to address chip\n"); +		goto Done; +	} + +	if (send_bytes (chip, &xaddr[4-alen], alen)) { +		printf ("i2c_write: send_bytes failed\n"); +		goto Done; +	} + +	if (send_bytes (chip, (char *)buf, len)) { +		printf ("i2c_write: send_bytes failed\n"); +		goto Done; +	} + +	ret = 0; +Done: +	mpc_reg_out (®s->mcr, 0, I2C_STA); +	return ret; +} + +int i2c_set_bus_num (unsigned int bus) +{ +	if (bus >= I2C_BUS_CNT) { +		return -1; +	} +	bus_num = bus; + +	return 0; +} + +unsigned int i2c_get_bus_num (void) +{ +	return bus_num; +} + +#endif	/* CONFIG_HARD_I2C */ diff --git a/roms/u-boot/arch/powerpc/cpu/mpc512x/ide.c b/roms/u-boot/arch/powerpc/cpu/mpc512x/ide.c new file mode 100644 index 00000000..dd113069 --- /dev/null +++ b/roms/u-boot/arch/powerpc/cpu/mpc512x/ide.c @@ -0,0 +1,111 @@ +/* + * (C) Copyright 2007-2009 DENX Software Engineering + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <command.h> +#include <asm/io.h> +#include <asm/processor.h> + +DECLARE_GLOBAL_DATA_PTR; + +#if defined(CONFIG_IDE_RESET) + +void ide_set_reset (int idereset) +{ +	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; +	debug ("ide_set_reset(%d)\n", idereset); + +	if (idereset) { +		out_be32(&im->pata.pata_ata_control, 0); +	} else { +		out_be32(&im->pata.pata_ata_control, FSL_ATA_CTRL_ATA_RST_B); +	} +	udelay(100); +} + +void init_ide_reset (void) +{ +	debug ("init_ide_reset\n"); + +	/* +	 * Clear the reset bit to reset the interface +	 * cf. RefMan MPC5121EE: 28.4.1 Resetting the ATA Bus +	 */ +	ide_set_reset(1); + +	/* Assert the reset bit to enable the interface */ +	ide_set_reset(0); + +} + +#define CALC_TIMING(t) (t + period - 1) / period + +int ide_preinit (void) +{ +	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; +	long t; +	const struct { +		short t0; +		short t1; +		short t2_8; +		short t2_16; +		short t2i; +		short t4; +		short t9; +		short tA; +	} pio_specs = { +		.t0    = 600, +		.t1    =  70, +		.t2_8  = 290, +		.t2_16 = 165, +		.t2i   =   0, +		.t4    =  30, +		.t9    =  20, +		.tA    =  50, +	}; +	union { +		u32 config; +		struct { +			u8 field1; +			u8 field2; +			u8 field3; +			u8 field4; +		}bytes; +	} cfg; + +	debug ("IDE preinit using PATA peripheral at IMMR-ADDR %08x\n", +		(u32)&im->pata); + +	/* Set the reset bit to 1 to enable the interface */ +	ide_set_reset(0); + +	/* Init timings : we use PIO mode 0 timings */ +	t = 1000000000 / gd->arch.ips_clk;	/* period in ns */ +	cfg.bytes.field1 = 3; +	cfg.bytes.field2 = 3; +	cfg.bytes.field3 = (pio_specs.t1 + t) / t; +	cfg.bytes.field4 = (pio_specs.t2_8 + t) / t; + +	out_be32(&im->pata.pata_time1, cfg.config); + +	cfg.bytes.field1 = (pio_specs.t2_8 + t) / t; +	cfg.bytes.field2 = (pio_specs.tA + t) / t + 2; +	cfg.bytes.field3 = 1; +	cfg.bytes.field4 = (pio_specs.t4 + t) / t; + +	out_be32(&im->pata.pata_time2, cfg.config); + +	cfg.config = in_be32(&im->pata.pata_time3); +	cfg.bytes.field1 = (pio_specs.t9 + t) / t; + +	out_be32(&im->pata.pata_time3, cfg.config); + +	debug ("PATA preinit complete.\n"); + +	return 0; +} + +#endif /* defined(CONFIG_IDE_RESET) */ diff --git a/roms/u-boot/arch/powerpc/cpu/mpc512x/interrupts.c b/roms/u-boot/arch/powerpc/cpu/mpc512x/interrupts.c new file mode 100644 index 00000000..3385aed1 --- /dev/null +++ b/roms/u-boot/arch/powerpc/cpu/mpc512x/interrupts.c @@ -0,0 +1,45 @@ +/* + * (C) Copyright 2000-2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Copyright 2004 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier:	GPL-2.0+ + * + * Derived from the MPC83xx code. + */ + +#include <common.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct irq_action { +	interrupt_handler_t *handler; +	void *arg; +	ulong count; +}; + +int interrupt_init_cpu (unsigned *decrementer_count) +{ +	*decrementer_count = get_tbclk () / CONFIG_SYS_HZ; + +	return 0; +} + +/* + * Install and free an interrupt handler. + */ +void +irq_install_handler (int irq, interrupt_handler_t * handler, void *arg) +{ +} + +void irq_free_handler (int irq) +{ +} + +void timer_interrupt_cpu (struct pt_regs *regs) +{ +	/* nothing to do here */ +	return; +} diff --git a/roms/u-boot/arch/powerpc/cpu/mpc512x/iopin.c b/roms/u-boot/arch/powerpc/cpu/mpc512x/iopin.c new file mode 100644 index 00000000..0b53c7b9 --- /dev/null +++ b/roms/u-boot/arch/powerpc/cpu/mpc512x/iopin.c @@ -0,0 +1,87 @@ +/* + * (C) Copyright 2008 + * Martha J Marx, Silicon Turnkey Express, mmarx@silicontkx.com + * mpc512x I/O pin/pad initialization for the ADS5121 board + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <linux/types.h> +#include <asm/io.h> + +void iopin_initialize(iopin_t *ioregs_init, int len) +{ +	short i, j, p; +	u32 *reg; +	immap_t *im = (immap_t *)CONFIG_SYS_IMMR; + +	reg = (u32 *)&(im->io_ctrl); + +	if (sizeof(ioregs_init) == 0) +		return; + +	for (i = 0; i < len; i++) { +		for (p = 0, j = ioregs_init[i].p_offset / sizeof(u_long); +			p < ioregs_init[i].nr_pins; p++, j++) { +			if (ioregs_init[i].bit_or) +				setbits_be32(reg + j, ioregs_init[i].val); +			else +				out_be32 (reg + j, ioregs_init[i].val); +		} +	} +	return; +} + +void iopin_initialize_bits(iopin_t *ioregs_init, int len) +{ +	short i, j, p; +	u32 *reg, mask; +	immap_t *im = (immap_t *)CONFIG_SYS_IMMR; + +	reg = (u32 *)&(im->io_ctrl); + +	/* iterate over table entries */ +	for (i = 0; i < len; i++) { +		/* iterate over pins within a table entry */ +		for (p = 0, j = ioregs_init[i].p_offset / sizeof(u_long); +			p < ioregs_init[i].nr_pins; p++, j++) { +			if (ioregs_init[i].bit_or & IO_PIN_OVER_EACH) { +				/* replace all settings at once */ +				out_be32(reg + j, ioregs_init[i].val); +			} else { +				/* +				 * only replace individual parts, but +				 * REPLACE them instead of just ORing +				 * them in and "inheriting" previously +				 * set bits which we don't want +				 */ +				mask = 0; +				if (ioregs_init[i].bit_or & IO_PIN_OVER_FMUX) +					mask |= IO_PIN_FMUX(3); + +				if (ioregs_init[i].bit_or & IO_PIN_OVER_HOLD) +					mask |= IO_PIN_HOLD(3); + +				if (ioregs_init[i].bit_or & IO_PIN_OVER_PULL) +					mask |= IO_PIN_PUD(1) | IO_PIN_PUE(1); + +				if (ioregs_init[i].bit_or & IO_PIN_OVER_STRIG) +					mask |= IO_PIN_ST(1); + +				if (ioregs_init[i].bit_or & IO_PIN_OVER_DRVSTR) +					mask |= IO_PIN_DS(3); +				/* +				 * DON'T do the "mask, then insert" +				 * in place on the register, it may +				 * break access to external hardware +				 * (like boot ROMs) when configuring +				 * LPB related pins, while the code to +				 * configure the pin is read from this +				 * very address region +				 */ +				clrsetbits_be32(reg + j, mask, +						ioregs_init[i].val & mask); +			} +		} +	} +} diff --git a/roms/u-boot/arch/powerpc/cpu/mpc512x/pci.c b/roms/u-boot/arch/powerpc/cpu/mpc512x/pci.c new file mode 100644 index 00000000..7ea5df29 --- /dev/null +++ b/roms/u-boot/arch/powerpc/cpu/mpc512x/pci.c @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2009-2010 DENX Software Engineering <wd@denx.de> + * Copyright (C) Freescale Semiconductor, Inc. 2006, 2007. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> + +#include <asm/io.h> +#include <asm/mmu.h> +#include <asm/global_data.h> +#include <pci.h> +#if defined(CONFIG_OF_LIBFDT) +#include <libfdt.h> +#include <fdt_support.h> +#endif + +DECLARE_GLOBAL_DATA_PTR; + +/* System RAM mapped to PCI space */ +#define CONFIG_PCI_SYS_MEM_BUS	CONFIG_SYS_SDRAM_BASE +#define CONFIG_PCI_SYS_MEM_PHYS	CONFIG_SYS_SDRAM_BASE + +static struct pci_controller pci_hose; + + +/************************************************************************** + * pci_init_board() + * + */ +void +pci_init_board(void) +{ +	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; +	volatile law512x_t *pci_law; +	volatile pot512x_t *pci_pot; +	volatile pcictrl512x_t *pci_ctrl; +	u16 reg16; +	u32 reg32; +	u32 dev; +	int i; +	struct pci_controller *hose; + +	/* Set PCI divider for 33MHz */ +	reg32 = in_be32(&im->clk.scfr[0]); +	reg32 &= ~(SCFR1_PCI_DIV_MASK); +	reg32 |= SCFR1_PCI_DIV << SCFR1_PCI_DIV_SHIFT; +	out_be32(&im->clk.scfr[0], reg32); + +	clrsetbits_be32(&im->clk.scfr[0], +			SCFR1_PCI_DIV_MASK, +			SCFR1_PCI_DIV << SCFR1_PCI_DIV_SHIFT +	); + +	pci_law = im->sysconf.pcilaw; +	pci_pot = im->ios.pot; +	pci_ctrl = &im->pci_ctrl; + +	hose = &pci_hose; + +	/* +	 * Release PCI RST Output signal +	 */ +	out_be32(&pci_ctrl->gcr, 0); +	udelay(2000); +	out_be32(&pci_ctrl->gcr, 1); + +	/* We need to wait at least a 1sec based on PCI specs */ +	for (i = 0; i < 1000; i++) +		udelay(1000); + +	/* +	 * Configure PCI Local Access Windows +	 */ +	out_be32(&pci_law[0].bar, CONFIG_SYS_PCI_MEM_PHYS & LAWBAR_BAR); +	out_be32(&pci_law[0].ar, LAWAR_EN | LAWAR_SIZE_512M); + +	out_be32(&pci_law[1].bar, CONFIG_SYS_PCI_IO_PHYS & LAWBAR_BAR); +	out_be32(&pci_law[1].ar, LAWAR_EN | LAWAR_SIZE_16M); + +	/* +	 * Configure PCI Outbound Translation Windows +	 */ + +	/* PCI mem space - prefetch */ +	out_be32(&pci_pot[0].potar, +		(CONFIG_SYS_PCI_MEM_BASE >> 12) & POTAR_TA_MASK); +	out_be32(&pci_pot[0].pobar, +		(CONFIG_SYS_PCI_MEM_PHYS >> 12) & POBAR_BA_MASK); +	out_be32(&pci_pot[0].pocmr, +		POCMR_EN | POCMR_PRE | POCMR_CM_256M); + +	/* PCI IO space */ +	out_be32(&pci_pot[1].potar, +		(CONFIG_SYS_PCI_IO_BASE >> 12) & POTAR_TA_MASK); +	out_be32(&pci_pot[1].pobar, +		(CONFIG_SYS_PCI_IO_PHYS >> 12) & POBAR_BA_MASK); +	out_be32(&pci_pot[1].pocmr, +		POCMR_EN | POCMR_IO | POCMR_CM_16M); + +	/* PCI mmio - non-prefetch mem space */ +	out_be32(&pci_pot[2].potar, +		(CONFIG_SYS_PCI_MMIO_BASE >> 12) & POTAR_TA_MASK); +	out_be32(&pci_pot[2].pobar, +		(CONFIG_SYS_PCI_MMIO_PHYS >> 12) & POBAR_BA_MASK); +	out_be32(&pci_pot[2].pocmr, +		POCMR_EN | POCMR_CM_256M); + +	/* +	 * Configure PCI Inbound Translation Windows +	 */ + +	/* we need RAM mapped to PCI space for the devices to +	 * access main memory */ +	out_be32(&pci_ctrl[0].pitar1, 0x0); +	out_be32(&pci_ctrl[0].pibar1, 0x0); +	out_be32(&pci_ctrl[0].piebar1, 0x0); +	out_be32(&pci_ctrl[0].piwar1, +		PIWAR_EN | PIWAR_PF | PIWAR_RTT_SNOOP | +		PIWAR_WTT_SNOOP | (__ilog2(gd->ram_size) - 1)); + +	hose->first_busno = 0; +	hose->last_busno = 0xff; + +	/* PCI memory prefetch space */ +	pci_set_region(hose->regions + 0, +		       CONFIG_SYS_PCI_MEM_BASE, +		       CONFIG_SYS_PCI_MEM_PHYS, +		       CONFIG_SYS_PCI_MEM_SIZE, +		       PCI_REGION_MEM|PCI_REGION_PREFETCH); + +	/* PCI memory space */ +	pci_set_region(hose->regions + 1, +		       CONFIG_SYS_PCI_MMIO_BASE, +		       CONFIG_SYS_PCI_MMIO_PHYS, +		       CONFIG_SYS_PCI_MMIO_SIZE, +		       PCI_REGION_MEM); + +	/* PCI IO space */ +	pci_set_region(hose->regions + 2, +		       CONFIG_SYS_PCI_IO_BASE, +		       CONFIG_SYS_PCI_IO_PHYS, +		       CONFIG_SYS_PCI_IO_SIZE, +		       PCI_REGION_IO); + +	/* System memory space */ +	pci_set_region(hose->regions + 3, +		       CONFIG_PCI_SYS_MEM_BUS, +		       CONFIG_PCI_SYS_MEM_PHYS, +		       gd->ram_size, +		       PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); + +	hose->region_count = 4; + +	pci_setup_indirect(hose, +			   (CONFIG_SYS_IMMR + 0x8300), +			   (CONFIG_SYS_IMMR + 0x8304)); + +	pci_register_hose(hose); + +	/* +	 * Write to Command register +	 */ +	reg16 = 0xff; +	dev = PCI_BDF(hose->first_busno, 0, 0); +	pci_hose_read_config_word(hose, dev, PCI_COMMAND, ®16); +	reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; +	pci_hose_write_config_word(hose, dev, PCI_COMMAND, reg16); + +	/* +	 * Clear non-reserved bits in status register. +	 */ +	pci_hose_write_config_word(hose, dev, PCI_STATUS, 0xffff); +	pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80); +	pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE, 0x08); + +#ifdef CONFIG_PCI_SCAN_SHOW +	printf("PCI:   Bus Dev VenId DevId Class Int\n"); +#endif +	/* +	 * Hose scan. +	 */ +	hose->last_busno = pci_hose_scan(hose); +} + +#if defined(CONFIG_OF_LIBFDT) +void ft_pci_setup(void *blob, bd_t *bd) +{ +	int nodeoffset; +	int tmp[2]; +	const char *path; + +	nodeoffset = fdt_path_offset(blob, "/aliases"); +	if (nodeoffset >= 0) { +		path = fdt_getprop(blob, nodeoffset, "pci", NULL); +		if (path) { +			tmp[0] = cpu_to_be32(pci_hose.first_busno); +			tmp[1] = cpu_to_be32(pci_hose.last_busno); +			do_fixup_by_path(blob, path, "bus-range", +				&tmp, sizeof(tmp), 1); + +			tmp[0] = cpu_to_be32(gd->pci_clk); +			do_fixup_by_path(blob, path, "clock-frequency", +				&tmp, sizeof(tmp[0]), 1); +		} +	} +} +#endif /* CONFIG_OF_LIBFDT */ diff --git a/roms/u-boot/arch/powerpc/cpu/mpc512x/serial.c b/roms/u-boot/arch/powerpc/cpu/mpc512x/serial.c new file mode 100644 index 00000000..42e0dc96 --- /dev/null +++ b/roms/u-boot/arch/powerpc/cpu/mpc512x/serial.c @@ -0,0 +1,443 @@ +/* + * (C) Copyright 2000 - 2010 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + * + * Based ont the MPC5200 PSC driver. + * Adapted for MPC512x by Jan Wrobel <wrr@semihalf.com> + */ + +/* + * Minimal serial functions needed to use one of the PSC ports + * as serial console interface. + */ + +#include <common.h> +#include <linux/compiler.h> +#include <asm/io.h> +#include <asm/processor.h> +#include <serial.h> + +DECLARE_GLOBAL_DATA_PTR; + +#if defined(CONFIG_PSC_CONSOLE) + +static void fifo_init (volatile psc512x_t *psc) +{ +	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; +	u32 tfsize, rfsize; + +	/* reset Rx & Tx fifo slice */ +	out_be32(&psc->rfcmd, PSC_FIFO_RESET_SLICE); +	out_be32(&psc->tfcmd, PSC_FIFO_RESET_SLICE); + +	/* disable Tx & Rx FIFO interrupts */ +	out_be32(&psc->rfintmask, 0); +	out_be32(&psc->tfintmask, 0); + +	switch (((u32)psc & 0xf00) >> 8) { +	case 0: +		tfsize = FIFOC_PSC0_TX_SIZE | (FIFOC_PSC0_TX_ADDR << 16); +		rfsize = FIFOC_PSC0_RX_SIZE | (FIFOC_PSC0_RX_ADDR << 16); +		break; +	case 1: +		tfsize = FIFOC_PSC1_TX_SIZE | (FIFOC_PSC1_TX_ADDR << 16); +		rfsize = FIFOC_PSC1_RX_SIZE | (FIFOC_PSC1_RX_ADDR << 16); +		break; +	case 2: +		tfsize = FIFOC_PSC2_TX_SIZE | (FIFOC_PSC2_TX_ADDR << 16); +		rfsize = FIFOC_PSC2_RX_SIZE | (FIFOC_PSC2_RX_ADDR << 16); +		break; +	case 3: +		tfsize = FIFOC_PSC3_TX_SIZE | (FIFOC_PSC3_TX_ADDR << 16); +		rfsize = FIFOC_PSC3_RX_SIZE | (FIFOC_PSC3_RX_ADDR << 16); +		break; +	case 4: +		tfsize = FIFOC_PSC4_TX_SIZE | (FIFOC_PSC4_TX_ADDR << 16); +		rfsize = FIFOC_PSC4_RX_SIZE | (FIFOC_PSC4_RX_ADDR << 16); +		break; +	case 5: +		tfsize = FIFOC_PSC5_TX_SIZE | (FIFOC_PSC5_TX_ADDR << 16); +		rfsize = FIFOC_PSC5_RX_SIZE | (FIFOC_PSC5_RX_ADDR << 16); +		break; +	case 6: +		tfsize = FIFOC_PSC6_TX_SIZE | (FIFOC_PSC6_TX_ADDR << 16); +		rfsize = FIFOC_PSC6_RX_SIZE | (FIFOC_PSC6_RX_ADDR << 16); +		break; +	case 7: +		tfsize = FIFOC_PSC7_TX_SIZE | (FIFOC_PSC7_TX_ADDR << 16); +		rfsize = FIFOC_PSC7_RX_SIZE | (FIFOC_PSC7_RX_ADDR << 16); +		break; +	case 8: +		tfsize = FIFOC_PSC8_TX_SIZE | (FIFOC_PSC8_TX_ADDR << 16); +		rfsize = FIFOC_PSC8_RX_SIZE | (FIFOC_PSC8_RX_ADDR << 16); +		break; +	case 9: +		tfsize = FIFOC_PSC9_TX_SIZE | (FIFOC_PSC9_TX_ADDR << 16); +		rfsize = FIFOC_PSC9_RX_SIZE | (FIFOC_PSC9_RX_ADDR << 16); +		break; +	case 10: +		tfsize = FIFOC_PSC10_TX_SIZE | (FIFOC_PSC10_TX_ADDR << 16); +		rfsize = FIFOC_PSC10_RX_SIZE | (FIFOC_PSC10_RX_ADDR << 16); +		break; +	case 11: +		tfsize = FIFOC_PSC11_TX_SIZE | (FIFOC_PSC11_TX_ADDR << 16); +		rfsize = FIFOC_PSC11_RX_SIZE | (FIFOC_PSC11_RX_ADDR << 16); +		break; +	default: +		return; +	} + +	out_be32(&psc->tfsize, tfsize); +	out_be32(&psc->rfsize, rfsize); + +	/* enable Tx & Rx FIFO slice */ +	out_be32(&psc->rfcmd, PSC_FIFO_ENABLE_SLICE); +	out_be32(&psc->tfcmd, PSC_FIFO_ENABLE_SLICE); + +	out_be32(&im->fifoc.fifoc_cmd, FIFOC_DISABLE_CLOCK_GATE); +	__asm__ volatile ("sync"); +} + +void serial_setbrg_dev(unsigned int idx) +{ +	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; +	volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx]; +	unsigned long baseclk, div; +	unsigned long baudrate; +	char buf[16]; +	char *br_env; + +	baudrate = gd->baudrate; +	if (idx != CONFIG_PSC_CONSOLE) { +		/* Allows setting baudrate for other serial devices +		 * on PSCx using environment. If not specified, use +		 * the same baudrate as for console. +		 */ +		sprintf(buf, "psc%d_baudrate", idx); +		br_env = getenv(buf); +		if (br_env) +			baudrate = simple_strtoul(br_env, NULL, 10); + +		debug("%s: idx %d, baudrate %ld\n", __func__, idx, baudrate); +	} + +	/* calculate divisor for setting PSC CTUR and CTLR registers */ +	baseclk = (gd->arch.ips_clk + 8) / 16; +	div = (baseclk + (baudrate / 2)) / baudrate; + +	out_8(&psc->ctur, (div >> 8) & 0xff); +	out_8(&psc->ctlr,  div & 0xff); /* set baudrate */ +} + +int serial_init_dev(unsigned int idx) +{ +	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; +	volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx]; +	u32 reg; + +	reg = in_be32(&im->clk.sccr[0]); +	out_be32(&im->clk.sccr[0], reg | CLOCK_SCCR1_PSC_EN(idx)); + +	fifo_init (psc); + +	/* set MR register to point to MR1 */ +	out_8(&psc->command, PSC_SEL_MODE_REG_1); + +	/* disable Tx/Rx */ +	out_8(&psc->command, PSC_TX_DISABLE | PSC_RX_DISABLE); + +	/* choose the prescaler	by 16 for the Tx/Rx clock generation */ +	out_be16(&psc->psc_clock_select, 0xdd00); + +	/* switch to UART mode */ +	out_be32(&psc->sicr, 0); + +	/* mode register points to mr1 */ +	/* configure parity, bit length and so on in mode register 1*/ +	out_8(&psc->mode, PSC_MODE_8_BITS | PSC_MODE_PARNONE); +	/* now, mode register points to mr2 */ +	out_8(&psc->mode, PSC_MODE_1_STOPBIT); + +	/* set baudrate */ +	serial_setbrg_dev(idx); + +	/* disable all interrupts */ +	out_be16(&psc->psc_imr, 0); + +	/* reset and enable Rx/Tx */ +	out_8(&psc->command, PSC_RST_RX); +	out_8(&psc->command, PSC_RST_TX); +	out_8(&psc->command, PSC_RX_ENABLE | PSC_TX_ENABLE); + +	return 0; +} + +int serial_uninit_dev(unsigned int idx) +{ +	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; +	volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx]; +	u32 reg; + +	out_8(&psc->command, PSC_RX_DISABLE | PSC_TX_DISABLE); +	reg = in_be32(&im->clk.sccr[0]); +	reg &= ~CLOCK_SCCR1_PSC_EN(idx); +	out_be32(&im->clk.sccr[0], reg); + +	return 0; +} + +void serial_putc_dev(unsigned int idx, const char c) +{ +	volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR; +	volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx]; + +	if (c == '\n') +		serial_putc_dev(idx, '\r'); + +	/* Wait for last character to go. */ +	while (!(in_be16(&psc->psc_status) & PSC_SR_TXEMP)) +		; + +	out_8(&psc->tfdata_8, c); +} + +void serial_putc_raw_dev(unsigned int idx, const char c) +{ +	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; +	volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx]; + +	/* Wait for last character to go. */ +	while (!(in_be16(&psc->psc_status) & PSC_SR_TXEMP)) +		; + +	out_8(&psc->tfdata_8, c); +} + +void serial_puts_dev(unsigned int idx, const char *s) +{ +	while (*s) +		serial_putc_dev(idx, *s++); +} + +int serial_getc_dev(unsigned int idx) +{ +	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; +	volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx]; + +	/* Wait for a character to arrive. */ +	while (in_be32(&psc->rfstat) & PSC_FIFO_EMPTY) +		; + +	return in_8(&psc->rfdata_8); +} + +int serial_tstc_dev(unsigned int idx) +{ +	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; +	volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx]; + +	return !(in_be32(&psc->rfstat) & PSC_FIFO_EMPTY); +} + +void serial_setrts_dev(unsigned int idx, int s) +{ +	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; +	volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx]; + +	if (s) { +		/* Assert RTS (become LOW) */ +		out_8(&psc->op1, 0x1); +	} +	else { +		/* Negate RTS (become HIGH) */ +		out_8(&psc->op0, 0x1); +	} +} + +int serial_getcts_dev(unsigned int idx) +{ +	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; +	volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx]; + +	return (in_8(&psc->ip) & 0x1) ? 0 : 1; +} +#endif /* CONFIG_PSC_CONSOLE */ + +#define DECLARE_PSC_SERIAL_FUNCTIONS(port) \ +	int serial##port##_init(void) \ +	{ \ +		return serial_init_dev(port); \ +	} \ +	int serial##port##_uninit(void) \ +	{ \ +		return serial_uninit_dev(port); \ +	} \ +	void serial##port##_setbrg(void) \ +	{ \ +		serial_setbrg_dev(port); \ +	} \ +	int serial##port##_getc(void) \ +	{ \ +		return serial_getc_dev(port); \ +	} \ +	int serial##port##_tstc(void) \ +	{ \ +		return serial_tstc_dev(port); \ +	} \ +	void serial##port##_putc(const char c) \ +	{ \ +		serial_putc_dev(port, c); \ +	} \ +	void serial##port##_puts(const char *s) \ +	{ \ +		serial_puts_dev(port, s); \ +	} + +#define INIT_PSC_SERIAL_STRUCTURE(port, __name) {	\ +	.name	= __name,				\ +	.start	= serial##port##_init,			\ +	.stop	= serial##port##_uninit,		\ +	.setbrg	= serial##port##_setbrg,		\ +	.getc	= serial##port##_getc,			\ +	.tstc	= serial##port##_tstc,			\ +	.putc	= serial##port##_putc,			\ +	.puts	= serial##port##_puts,			\ +} + +#if defined(CONFIG_SYS_PSC1) +DECLARE_PSC_SERIAL_FUNCTIONS(1); +struct serial_device serial1_device = +INIT_PSC_SERIAL_STRUCTURE(1, "psc1"); +#endif + +#if defined(CONFIG_SYS_PSC3) +DECLARE_PSC_SERIAL_FUNCTIONS(3); +struct serial_device serial3_device = +INIT_PSC_SERIAL_STRUCTURE(3, "psc3"); +#endif + +#if defined(CONFIG_SYS_PSC4) +DECLARE_PSC_SERIAL_FUNCTIONS(4); +struct serial_device serial4_device = +INIT_PSC_SERIAL_STRUCTURE(4, "psc4"); +#endif + +#if defined(CONFIG_SYS_PSC6) +DECLARE_PSC_SERIAL_FUNCTIONS(6); +struct serial_device serial6_device = +INIT_PSC_SERIAL_STRUCTURE(6, "psc6"); +#endif + +__weak struct serial_device *default_serial_console(void) +{ +#if (CONFIG_PSC_CONSOLE == 3) +	return &serial3_device; +#elif (CONFIG_PSC_CONSOLE == 6) +	return &serial6_device; +#else +#error "invalid CONFIG_PSC_CONSOLE" +#endif +} + +void mpc512x_serial_initialize(void) +{ +#if defined(CONFIG_SYS_PSC1) +	serial_register(&serial1_device); +#endif +#if defined(CONFIG_SYS_PSC3) +	serial_register(&serial3_device); +#endif +#if defined(CONFIG_SYS_PSC4) +	serial_register(&serial4_device); +#endif +#if defined(CONFIG_SYS_PSC6) +	serial_register(&serial6_device); +#endif +} + +#include <stdio_dev.h> +/* + * Routines for communication with serial devices over PSC + */ +/* Bitfield for initialized PSCs */ +static unsigned int initialized; + +struct stdio_dev *open_port(int num, int baudrate) +{ +	struct stdio_dev *port; +	char env_var[16]; +	char env_val[10]; +	char name[7]; + +	if (num < 0 || num > 11) +		return NULL; + +	sprintf(name, "psc%d", num); +	port = stdio_get_by_name(name); +	if (!port) +		return NULL; + +	if (!test_bit(num, &initialized)) { +		sprintf(env_var, "psc%d_baudrate", num); +		sprintf(env_val, "%d", baudrate); +		setenv(env_var, env_val); + +		if (port->start()) +			return NULL; + +		set_bit(num, &initialized); +	} + +	return port; +} + +int close_port(int num) +{ +	struct stdio_dev *port; +	int ret; +	char name[7]; + +	if (num < 0 || num > 11) +		return -1; + +	sprintf(name, "psc%d", num); +	port = stdio_get_by_name(name); +	if (!port) +		return -1; + +	ret = port->stop(); +	clear_bit(num, &initialized); + +	return ret; +} + +int write_port(struct stdio_dev *port, char *buf) +{ +	if (!port || !buf) +		return -1; + +	port->puts(buf); + +	return 0; +} + +int read_port(struct stdio_dev *port, char *buf, int size) +{ +	int cnt = 0; + +	if (!port || !buf) +		return -1; + +	if (!size) +		return 0; + +	while (port->tstc()) { +		buf[cnt++] = port->getc(); +		if (cnt > size) +			break; +	} + +	return cnt; +} diff --git a/roms/u-boot/arch/powerpc/cpu/mpc512x/speed.c b/roms/u-boot/arch/powerpc/cpu/mpc512x/speed.c new file mode 100644 index 00000000..95069cad --- /dev/null +++ b/roms/u-boot/arch/powerpc/cpu/mpc512x/speed.c @@ -0,0 +1,137 @@ +/* + * (C) Copyright 2000-2009 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Copyright (C) 2004-2006 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier:	GPL-2.0+ + * + * Based on the MPC83xx code. + */ + +#include <common.h> +#include <command.h> +#include <asm/io.h> +#include <asm/processor.h> + +DECLARE_GLOBAL_DATA_PTR; + +static int spmf_mult[] = { +	68, 1, 12, 16, +	20, 24, 28, 32, +	36, 40, 44, 48, +	52, 56, 60, 64 +}; + +static int cpmf_mult[][2] = { +	{0, 1}, {0, 1}, /* 0 and 1 are not valid */ +	{1, 1}, {3, 2}, +	{2, 1}, {5, 2}, +	{3, 1}, {7, 2}, +	{0, 1}, {0, 1}, /* and all above 7 are not valid too */ +	{0, 1}, {0, 1}, +	{0, 1}, {0, 1}, +	{0, 1}, {0, 1} +}; + +static int sys_dividors[][2] = { +	{2, 1}, {5, 2}, {3, 1}, {7, 2}, {4, 1}, +	{9, 2}, {5, 1}, {7, 1}, {6, 1}, {8, 1}, +	{9, 1}, {11, 1}, {10, 1}, {12, 1}, {13, 1}, +	{15, 1}, {14, 1}, {16, 1}, {17, 1}, {19, 1}, +	{18, 1}, {20, 1}, {21, 1}, {23, 1}, {22, 1}, +	{24, 1}, {25, 1}, {27, 1}, {26, 1}, {28, 1}, +	{29, 1}, {31, 1}, {30, 1}, {32, 1}, {33, 1} +}; + +int get_clocks (void) +{ +	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; +	u8 spmf; +	u8 cpmf; +	u8 sys_div; +	u8 ips_div; +	u8 pci_div; +	u32 ref_clk = CONFIG_SYS_MPC512X_CLKIN; +	u32 spll; +	u32 sys_clk; +	u32 core_clk; +	u32 csb_clk; +	u32 ips_clk; +	u32 pci_clk; +	u32 reg; + +	reg = in_be32(&im->sysconf.immrbar); +	if ((reg & IMMRBAR_BASE_ADDR) != (u32) im) +		return -1; + +	reg = in_be32(&im->clk.spmr); +	spmf = (reg & SPMR_SPMF) >> SPMR_SPMF_SHIFT; +	spll = ref_clk * spmf_mult[spmf]; + +	reg = in_be32(&im->clk.scfr[1]); +	sys_div = (reg & SCFR2_SYS_DIV) >> SCFR2_SYS_DIV_SHIFT; +	sys_clk = (spll * sys_dividors[sys_div][1]) / sys_dividors[sys_div][0]; + +	csb_clk = sys_clk / 2; + +	reg = in_be32(&im->clk.spmr); +	cpmf = (reg & SPMR_CPMF) >> SPMR_CPMF_SHIFT; +	core_clk = (csb_clk * cpmf_mult[cpmf][0]) / cpmf_mult[cpmf][1]; + +	reg = in_be32(&im->clk.scfr[0]); +	ips_div = (reg & SCFR1_IPS_DIV_MASK) >> SCFR1_IPS_DIV_SHIFT; +	if (ips_div != 0) { +		ips_clk = csb_clk / ips_div; +	} else { +		/* in case we cannot get a sane IPS divisor, fail gracefully */ +		ips_clk = 0; +	} + +	reg = in_be32(&im->clk.scfr[0]); +	pci_div = (reg & SCFR1_PCI_DIV_MASK) >> SCFR1_PCI_DIV_SHIFT; +	if (pci_div != 0) { +		pci_clk = csb_clk / pci_div; +	} else { +		/* in case we cannot get a sane IPS divisor, fail gracefully */ +		pci_clk = 333333; +	} + +	gd->arch.ips_clk = ips_clk; +	gd->pci_clk = pci_clk; +	gd->arch.csb_clk = csb_clk; +	gd->cpu_clk = core_clk; +	gd->bus_clk = csb_clk; +	return 0; + +} + +/******************************************** + * get_bus_freq + * return system bus freq in Hz + *********************************************/ +ulong get_bus_freq (ulong dummy) +{ +	return gd->arch.csb_clk; +} + +int do_clocks (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) +{ +	char buf[32]; + +	printf("Clock configuration:\n"); +	printf("  CPU:                 %-4s MHz\n", strmhz(buf, gd->cpu_clk)); +	printf("  Coherent System Bus: %-4s MHz\n", +	       strmhz(buf, gd->arch.csb_clk)); +	printf("  IPS Bus:             %-4s MHz\n", +	       strmhz(buf, gd->arch.ips_clk)); +	printf("  PCI:                 %-4s MHz\n", strmhz(buf, gd->pci_clk)); +	printf("  DDR:                 %-4s MHz\n", +	       strmhz(buf, 2 * gd->arch.csb_clk)); +	return 0; +} + +U_BOOT_CMD(clocks, 1, 0, do_clocks, +	"print clock configuration", +	"    clocks" +); diff --git a/roms/u-boot/arch/powerpc/cpu/mpc512x/start.S b/roms/u-boot/arch/powerpc/cpu/mpc512x/start.S new file mode 100644 index 00000000..6c331d10 --- /dev/null +++ b/roms/u-boot/arch/powerpc/cpu/mpc512x/start.S @@ -0,0 +1,692 @@ +/* + * Copyright (C) 1998  Dan Malek <dmalek@jlc.net> + * Copyright (C) 1999  Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se> + * Copyright (C) 2000-2009 Wolfgang Denk <wd@denx.de> + * Copyright Freescale Semiconductor, Inc. 2004, 2006. + * + * SPDX-License-Identifier:	GPL-2.0+ + * + * Based on the MPC83xx code. + */ + +/* + *  U-Boot - Startup Code for MPC512x based Embedded Boards + */ + +#include <asm-offsets.h> +#include <config.h> +#ifndef  CONFIG_IDENT_STRING +#define  CONFIG_IDENT_STRING "MPC512X" +#endif +#include <version.h> + +#define CONFIG_521X	1		/* needed for Linux kernel header files*/ + +#include <asm/immap_512x.h> +#include "asm-offsets.h" + +#include <ppc_asm.tmpl> +#include <ppc_defs.h> + +#include <asm/cache.h> +#include <asm/mmu.h> +#include <asm/u-boot.h> + +/* + * Floating Point enable, Machine Check and Recoverable Interr. + */ +#undef	MSR_KERNEL +#ifdef DEBUG +#define MSR_KERNEL (MSR_FP|MSR_RI) +#else +#define MSR_KERNEL (MSR_FP|MSR_ME|MSR_RI) +#endif + +/* Macros for manipulating CSx_START/STOP */ +#define START_REG(start)	((start) >> 16) +#define STOP_REG(start, size)	(((start) + (size) - 1) >> 16) + +/* + * Set up GOT: Global Offset Table + * + * Use r12 to access the GOT + */ +	START_GOT +	GOT_ENTRY(_GOT2_TABLE_) +	GOT_ENTRY(_FIXUP_TABLE_) + +	GOT_ENTRY(_start) +	GOT_ENTRY(_start_of_vectors) +	GOT_ENTRY(_end_of_vectors) +	GOT_ENTRY(transfer_to_handler) + +	GOT_ENTRY(__init_end) +	GOT_ENTRY(__bss_end) +	GOT_ENTRY(__bss_start) +	END_GOT + +/* + * Magic number and version string + */ +	.long	0x27051956		/* U-Boot Magic Number */ +	.globl	version_string +version_string: +	.ascii U_BOOT_VERSION_STRING, "\0" + +/* + * Vector Table + */ +	.text +	. = EXC_OFF_SYS_RESET + +	.globl	_start +	/* Start from here after reset/power on */ +_start: +	b	boot_cold + +	.globl	_start_of_vectors +_start_of_vectors: + +/* Machine check */ +	STD_EXCEPTION(0x200, MachineCheck, MachineCheckException) + +/* Data Storage exception. */ +	STD_EXCEPTION(0x300, DataStorage, UnknownException) + +/* Instruction Storage exception. */ +	STD_EXCEPTION(0x400, InstStorage, UnknownException) + +/* External Interrupt exception. */ +	STD_EXCEPTION(0x500, ExtInterrupt, UnknownException) + +/* Alignment exception. */ +	. = 0x600 +Alignment: +	EXCEPTION_PROLOG(SRR0, SRR1) +	mfspr	r4,DAR +	stw	r4,_DAR(r21) +	mfspr	r5,DSISR +	stw	r5,_DSISR(r21) +	addi	r3,r1,STACK_FRAME_OVERHEAD +	EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE) + +/* Program check exception */ +	. = 0x700 +ProgramCheck: +	EXCEPTION_PROLOG(SRR0, SRR1) +	addi	r3,r1,STACK_FRAME_OVERHEAD +	EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException, +		MSR_KERNEL, COPY_EE) + +/* Floating Point Unit unavailable exception */ +	STD_EXCEPTION(0x800, FPUnavailable, UnknownException) + +/* Decrementer */ +	STD_EXCEPTION(0x900, Decrementer, timer_interrupt) + +/* Critical interrupt */ +	STD_EXCEPTION(0xa00, Critical, UnknownException) + +/* System Call */ +	STD_EXCEPTION(0xc00, SystemCall, UnknownException) + +/* Trace interrupt */ +	STD_EXCEPTION(0xd00, Trace, UnknownException) + +/* Performance Monitor interrupt */ +	STD_EXCEPTION(0xf00, PerfMon, UnknownException) + +/* Intruction Translation Miss */ +	STD_EXCEPTION(0x1000, InstructionTLBMiss, UnknownException) + +/* Data Load Translation Miss */ +	STD_EXCEPTION(0x1100, DataLoadTLBMiss, UnknownException) + +/* Data Store Translation Miss */ +	STD_EXCEPTION(0x1200, DataStoreTLBMiss, UnknownException) + +/* Instruction Address Breakpoint */ +	STD_EXCEPTION(0x1300, InstructionAddrBreakpoint, DebugException) + +/* System Management interrupt */ +	STD_EXCEPTION(0x1400, SystemMgmtInterrupt, UnknownException) + +	.globl	_end_of_vectors +_end_of_vectors: + +	. = 0x3000 +boot_cold: +	/* Save msr contents */ +	mfmsr	r5 + +	/* Set IMMR area to our preferred location */ +	lis	r4, CONFIG_DEFAULT_IMMR@h +	lis	r3, CONFIG_SYS_IMMR@h +	ori	r3, r3, CONFIG_SYS_IMMR@l +	stw	r3, IMMRBAR(r4) +	mtspr	MBAR, r3		/* IMMRBAR is mirrored into the MBAR SPR (311) */ + +	/* Initialise the machine */ +	bl	cpu_early_init + +	/* +	 * Set up Local Access Windows: +	 * +	 * 1) Boot/CS0 (boot FLASH) +	 * 2) On-chip SRAM (initial stack purposes) +	 */ + +	/* Boot CS/CS0 window range */ +	lis     r3, CONFIG_SYS_IMMR@h +	ori     r3, r3, CONFIG_SYS_IMMR@l + +	lis	r4, START_REG(CONFIG_SYS_FLASH_BASE) +	ori	r4, r4, STOP_REG(CONFIG_SYS_FLASH_BASE, CONFIG_SYS_FLASH_SIZE) +	stw	r4, LPCS0AW(r3) + +	/* +	 * The SRAM window has a fixed size (256K), so only the start address +	 * is necessary +	 */ +	lis	r4, START_REG(CONFIG_SYS_SRAM_BASE) & 0xff00 +	stw	r4, SRAMBAR(r3) + +	/* +	 * According to MPC5121e RM, configuring local access windows should +	 * be followed by a dummy read of the config register that was +	 * modified last and an isync +	 */ +	lwz	r4, SRAMBAR(r3) +	isync + +	/* +	 * Set configuration of the Boot/CS0, the SRAM window does not have a +	 * config register so no params can be set for it +	 */ +	lis     r3, (CONFIG_SYS_IMMR + LPC_OFFSET)@h +	ori     r3, r3, (CONFIG_SYS_IMMR + LPC_OFFSET)@l + +	lis     r4, CONFIG_SYS_CS0_CFG@h +	ori     r4, r4, CONFIG_SYS_CS0_CFG@l +	stw     r4, CS0_CONFIG(r3) + +	/* Master enable all CS's */ +	lis	r4, CS_CTRL_ME@h +	ori	r4, r4, CS_CTRL_ME@l +	stw	r4, CS_CTRL(r3) + +	lis	r4, (CONFIG_SYS_MONITOR_BASE)@h +	ori	r4, r4, (CONFIG_SYS_MONITOR_BASE)@l +	addi	r5, r4, in_flash - _start + EXC_OFF_SYS_RESET +	mtlr	r5 +	blr + +in_flash: +	lis	r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@h +	ori	r1, r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@l + +	li	r0, 0		/* Make room for stack frame header and	*/ +	stwu	r0, -4(r1)	/* clear final stack frame so that	*/ +	stwu	r0, -4(r1)	/* stack backtraces terminate cleanly	*/ + +	/* let the C-code set up the rest			*/ +	/*							*/ +	/* Be careful to keep code relocatable & stack humble	*/ +	/*------------------------------------------------------*/ + +	GET_GOT			/* initialize GOT access	*/ + +	/* r3: IMMR */ +	lis	r3, CONFIG_SYS_IMMR@h +	/* run low-level CPU init code (in Flash) */ +	bl	cpu_init_f + +	/* run 1st part of board init code (in Flash) */ +	bl	board_init_f + +	/* NOTREACHED - board_init_f() does not return */ + +/* + * This code finishes saving the registers to the exception frame + * and jumps to the appropriate handler for the exception. + * Register r21 is pointer into trap frame, r1 has new stack pointer. + */ +	.globl	transfer_to_handler +transfer_to_handler: +	stw	r22,_NIP(r21) +	lis	r22,MSR_POW@h +	andc	r23,r23,r22 +	stw	r23,_MSR(r21) +	SAVE_GPR(7, r21) +	SAVE_4GPRS(8, r21) +	SAVE_8GPRS(12, r21) +	SAVE_8GPRS(24, r21) +	mflr	r23 +	andi.	r24,r23,0x3f00		/* get vector offset */ +	stw	r24,TRAP(r21) +	li	r22,0 +	stw	r22,RESULT(r21) +	lwz	r24,0(r23)		/* virtual address of handler */ +	lwz	r23,4(r23)		/* where to go when done */ +	mtspr	SRR0,r24 +	mtspr	SRR1,r20 +	mtlr	r23 +	SYNC +	rfi				/* jump to handler, enable MMU */ + +int_return: +	mfmsr	r28		/* Disable interrupts */ +	li	r4,0 +	ori	r4,r4,MSR_EE +	andc	r28,r28,r4 +	SYNC			/* Some chip revs need this... */ +	mtmsr	r28 +	SYNC +	lwz	r2,_CTR(r1) +	lwz	r0,_LINK(r1) +	mtctr	r2 +	mtlr	r0 +	lwz	r2,_XER(r1) +	lwz	r0,_CCR(r1) +	mtspr	XER,r2 +	mtcrf	0xFF,r0 +	REST_10GPRS(3, r1) +	REST_10GPRS(13, r1) +	REST_8GPRS(23, r1) +	REST_GPR(31, r1) +	lwz	r2,_NIP(r1)	/* Restore environment */ +	lwz	r0,_MSR(r1) +	mtspr	SRR0,r2 +	mtspr	SRR1,r0 +	lwz	r0,GPR0(r1) +	lwz	r2,GPR2(r1) +	lwz	r1,GPR1(r1) +	SYNC +	rfi + +/* + * This code initialises the machine, it expects original MSR contents to be in r5. + */ +cpu_early_init: +	/* Initialize machine status; enable machine check interrupt */ +	/*-----------------------------------------------------------*/ + +	li	r3, MSR_KERNEL			/* Set ME and RI flags */ +	rlwimi	r3, r5, 0, 25, 25		/* preserve IP bit */ +#ifdef DEBUG +	rlwimi	r3, r5, 0, 21, 22		/* debugger might set SE, BE bits */ +#endif +	mtmsr	r3 +	SYNC +	mtspr	SRR1, r3			/* Mirror current MSR state in SRR1 */ + +	lis	r3, CONFIG_SYS_IMMR@h + +#if defined(CONFIG_WATCHDOG) +	/* Initialise the watchdog and reset it */ +	/*--------------------------------------*/ +	lis r4, CONFIG_SYS_WATCHDOG_VALUE +	ori r4, r4, (SWCRR_SWEN | SWCRR_SWRI | SWCRR_SWPR) +	stw r4, SWCRR(r3) + +	/* reset */ +	li	r4, 0x556C +	sth	r4, SWSRR@l(r3) +	li	r4, 0x0 +	ori	r4, r4, 0xAA39 +	sth	r4, SWSRR@l(r3) +#else +	/* Disable the watchdog */ +	/*----------------------*/ +	lwz r4, SWCRR(r3) +	/* +	 * Check to see if it's enabled for disabling: once disabled by s/w +	 * it's not possible to re-enable it +	 */ +	andi. r4, r4, 0x4 +	beq 1f +	xor r4, r4, r4 +	stw r4, SWCRR(r3) +1: +#endif /* CONFIG_WATCHDOG */ + +	/* Initialize the Hardware Implementation-dependent Registers */ +	/* HID0 also contains cache control			*/ +	/*------------------------------------------------------*/ +	lis	r3, CONFIG_SYS_HID0_INIT@h +	ori	r3, r3, CONFIG_SYS_HID0_INIT@l +	SYNC +	mtspr	HID0, r3 + +	lis	r3, CONFIG_SYS_HID0_FINAL@h +	ori	r3, r3, CONFIG_SYS_HID0_FINAL@l +	SYNC +	mtspr	HID0, r3 + +	lis	r3, CONFIG_SYS_HID2@h +	ori	r3, r3, CONFIG_SYS_HID2@l +	SYNC +	mtspr	HID2, r3 +	sync +	blr + + +/* Cache functions. + * + * Note: requires that all cache bits in + * HID0 are in the low half word. + */ +	.globl	icache_enable +icache_enable: +	mfspr	r3, HID0 +	ori	r3, r3, HID0_ICE +	lis	r4, 0 +	ori	r4, r4, HID0_ILOCK +	andc	r3, r3, r4 +	ori	r4, r3, HID0_ICFI +	isync +	mtspr	HID0, r4    /* sets enable and invalidate, clears lock */ +	isync +	mtspr	HID0, r3	/* clears invalidate */ +	blr + +	.globl	icache_disable +icache_disable: +	mfspr	r3, HID0 +	lis	r4, 0 +	ori	r4, r4, HID0_ICE|HID0_ILOCK +	andc	r3, r3, r4 +	ori	r4, r3, HID0_ICFI +	isync +	mtspr	HID0, r4     /* sets invalidate, clears enable and lock*/ +	isync +	mtspr	HID0, r3	/* clears invalidate */ +	blr + +	.globl	icache_status +icache_status: +	mfspr	r3, HID0 +	rlwinm	r3, r3, (31 - HID0_ICE_SHIFT + 1), 31, 31 +	blr + +	.globl	dcache_enable +dcache_enable: +	mfspr	r3, HID0 +	li	r5, HID0_DCFI|HID0_DLOCK +	andc	r3, r3, r5 +	mtspr	HID0, r3		/* no invalidate, unlock */ +	ori	r3, r3, HID0_DCE +	ori	r5, r3, HID0_DCFI +	mtspr	HID0, r5		/* enable + invalidate */ +	mtspr	HID0, r3		/* enable */ +	sync +	blr + +	.globl	dcache_disable +dcache_disable: +	mfspr	r3, HID0 +	lis	r4, 0 +	ori	r4, r4, HID0_DCE|HID0_DLOCK +	andc	r3, r3, r4 +	ori	r4, r3, HID0_DCI +	sync +	mtspr	HID0, r4	/* sets invalidate, clears enable and lock */ +	sync +	mtspr	HID0, r3	/* clears invalidate */ +	blr + +	.globl	dcache_status +dcache_status: +	mfspr	r3, HID0 +	rlwinm	r3, r3, (31 - HID0_DCE_SHIFT + 1), 31, 31 +	blr + +	.globl get_pvr +get_pvr: +	mfspr	r3, PVR +	blr + +/*-------------------------------------------------------------------*/ + +/* + * void relocate_code (addr_sp, gd, addr_moni) + * + * This "function" does not return, instead it continues in RAM + * after relocating the monitor code. + * + * r3 = dest + * r4 = src + * r5 = length in bytes + * r6 = cachelinesize + */ +	.globl	relocate_code +relocate_code: +	mr	r1,  r3		/* Set new stack pointer	*/ +	mr	r9,  r4		/* Save copy of Global Data pointer */ +	mr	r10, r5		/* Save copy of Destination Address */ + +	GET_GOT +	mr	r3,  r5				/* Destination Address */ +	lis	r4, CONFIG_SYS_MONITOR_BASE@h		/* Source      Address */ +	ori	r4, r4, CONFIG_SYS_MONITOR_BASE@l +	lwz	r5, GOT(__init_end) +	sub	r5, r5, r4 +	li	r6, CONFIG_SYS_CACHELINE_SIZE		/* Cache Line Size */ + +	/* +	 * Fix GOT pointer: +	 * +	 * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) +	 *		+ Destination Address +	 * +	 * Offset: +	 */ +	sub	r15, r10, r4 + +	/* First our own GOT */ +	add	r12, r12, r15 +	/* then the one used by the C code */ +	add	r30, r30, r15 + +	/* +	 * Now relocate code +	 */ +	cmplw	cr1,r3,r4 +	addi	r0,r5,3 +	srwi.	r0,r0,2 +	beq	cr1,4f		/* In place copy is not necessary */ +	beq	7f		/* Protect against 0 count	  */ +	mtctr	r0 +	bge	cr1,2f +	la	r8,-4(r4) +	la	r7,-4(r3) + +	/* copy */ +1:	lwzu	r0,4(r8) +	stwu	r0,4(r7) +	bdnz	1b + +	addi	r0,r5,3 +	srwi.	r0,r0,2 +	mtctr	r0 +	la	r8,-4(r4) +	la	r7,-4(r3) + +	/* and compare */ +20:	lwzu	r20,4(r8) +	lwzu	r21,4(r7) +	xor. r22, r20, r21 +	bne  30f +	bdnz	20b +	b 4f + +	/* compare failed */ +30:	li r3, 0 +	blr + +2:	slwi	r0,r0,2 /* re copy in reverse order ... y do we needed it? */ +	add	r8,r4,r0 +	add	r7,r3,r0 +3:	lwzu	r0,-4(r8) +	stwu	r0,-4(r7) +	bdnz	3b + +/* + * Now flush the cache: note that we must start from a cache aligned + * address. Otherwise we might miss one cache line. + */ +4:	cmpwi	r6,0 +	add	r5,r3,r5 +	beq	7f		/* Always flush prefetch queue in any case */ +	subi	r0,r6,1 +	andc	r3,r3,r0 +	mr	r4,r3 +5:	dcbst	0,r4 +	add	r4,r4,r6 +	cmplw	r4,r5 +	blt	5b +	sync			/* Wait for all dcbst to complete on bus */ +	mr	r4,r3 +6:	icbi	0,r4 +	add	r4,r4,r6 +	cmplw	r4,r5 +	blt	6b +7:	sync			/* Wait for all icbi to complete on bus	*/ +	isync + +/* + * We are done. Do not return, instead branch to second part of board + * initialization, now running from RAM. + */ +	addi	r0, r10, in_ram - _start + EXC_OFF_SYS_RESET +	mtlr	r0 +	blr + +in_ram: +	/* +	 * Relocation Function, r12 point to got2+0x8000 +	 * +	 * Adjust got2 pointers, no need to check for 0, this code +	 * already puts a few entries in the table. +	 */ +	li	r0,__got2_entries@sectoff@l +	la	r3,GOT(_GOT2_TABLE_) +	lwz	r11,GOT(_GOT2_TABLE_) +	mtctr	r0 +	sub	r11,r3,r11 +	addi	r3,r3,-4 +1:	lwzu	r0,4(r3) +	cmpwi	r0,0 +	beq-	2f +	add	r0,r0,r11 +	stw	r0,0(r3) +2:	bdnz	1b + +	/* +	 * Now adjust the fixups and the pointers to the fixups +	 * in case we need to move ourselves again. +	 */ +	li	r0,__fixup_entries@sectoff@l +	lwz	r3,GOT(_FIXUP_TABLE_) +	cmpwi	r0,0 +	mtctr	r0 +	addi	r3,r3,-4 +	beq	4f +3:	lwzu	r4,4(r3) +	lwzux	r0,r4,r11 +	cmpwi	r0,0 +	add	r0,r0,r11 +	stw	r4,0(r3) +	beq-	5f +	stw	r0,0(r4) +5:	bdnz	3b +4: +clear_bss: +	/* +	 * Now clear BSS segment +	 */ +	lwz	r3,GOT(__bss_start) +	lwz	r4,GOT(__bss_end) + +	cmplw	0, r3, r4 +	beq	6f + +	li	r0, 0 +5: +	stw	r0, 0(r3) +	addi	r3, r3, 4 +	cmplw	0, r3, r4 +	bne	5b +6: +	mr	r3, r9		/* Global Data pointer		*/ +	mr	r4, r10		/* Destination Address		*/ +	bl	board_init_r + +	/* +	 * Copy exception vector code to low memory +	 * +	 * r3: dest_addr +	 * r7: source address, r8: end address, r9: target address +	 */ +	.globl	trap_init +trap_init: +	mflr	r4		/* save link register */ +	GET_GOT +	lwz	r7, GOT(_start) +	lwz	r8, GOT(_end_of_vectors) + +	li	r9, 0x100	/* reset vector at 0x100 */ + +	cmplw	0, r7, r8 +	bgelr			/* return if r7>=r8 - just in case */ +1: +	lwz	r0, 0(r7) +	stw	r0, 0(r9) +	addi	r7, r7, 4 +	addi	r9, r9, 4 +	cmplw	0, r7, r8 +	bne	1b + +	/* +	 * relocate `hdlr' and `int_return' entries +	 */ +	li	r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET +	li	r8, Alignment - _start + EXC_OFF_SYS_RESET +2: +	bl	trap_reloc +	addi	r7, r7, 0x100		/* next exception vector */ +	cmplw	0, r7, r8 +	blt	2b + +	li	r7, .L_Alignment - _start + EXC_OFF_SYS_RESET +	bl	trap_reloc + +	li	r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET +	bl	trap_reloc + +	li	r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET +	li	r8, SystemCall - _start + EXC_OFF_SYS_RESET +3: +	bl	trap_reloc +	addi	r7, r7, 0x100		/* next exception vector */ +	cmplw	0, r7, r8 +	blt	3b + +	li	r7, .L_Trace - _start + EXC_OFF_SYS_RESET +	li	r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET +4: +	bl	trap_reloc +	addi	r7, r7, 0x100		/* next exception vector */ +	cmplw	0, r7, r8 +	blt	4b + +	mfmsr	r3			/* now that the vectors have */ +	lis	r7, MSR_IP@h		/* relocated into low memory */ +	ori	r7, r7, MSR_IP@l	/* MSR[IP] can be turned off */ +	andc	r3, r3, r7		/* (if it was on) */ +	SYNC				/* Some chip revs need this... */ +	mtmsr	r3 +	SYNC + +	mtlr	r4			/* restore link register    */ +	blr diff --git a/roms/u-boot/arch/powerpc/cpu/mpc512x/traps.c b/roms/u-boot/arch/powerpc/cpu/mpc512x/traps.c new file mode 100644 index 00000000..9f5bcd7f --- /dev/null +++ b/roms/u-boot/arch/powerpc/cpu/mpc512x/traps.c @@ -0,0 +1,190 @@ +/* + * (C) Copyright 2000 - 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Copyright (C) 1995-1996  Gary Thomas (gdt@linuxppc.org) + * + * SPDX-License-Identifier:	GPL-2.0+ + * + * Derived from the MPC83xx code. + */ + +/* + * This file handles the architecture-dependent parts of hardware + * exceptions + */ + +#include <common.h> +#include <kgdb.h> +#include <asm/processor.h> + +DECLARE_GLOBAL_DATA_PTR; + +extern unsigned long search_exception_table(unsigned long); + +/* + * End of addressable memory.  This may be less than the actual + * amount of memory on the system if we're unable to keep all + * the memory mapped in. + */ +#define END_OF_MEM (gd->bd->bi_memstart + get_effective_memsize()) + +/* + * Trap & Exception support + */ + +static void print_backtrace(unsigned long *sp) +{ +	int cnt = 0; +	unsigned long i; + +	puts("Call backtrace: "); +	while (sp) { +		if ((uint)sp > END_OF_MEM) +			break; + +		i = sp[1]; +		if (cnt++ % 7 == 0) +			putc('\n'); +		printf("%08lX ", i); +		if (cnt > 32) break; +		sp = (unsigned long *) *sp; +	} +	putc('\n'); +} + +void show_regs(struct pt_regs *regs) +{ +	int i; + +	printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n", +	       regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar); +	printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n", +	       regs->msr, regs->msr & MSR_EE ? 1 : 0, regs->msr & MSR_PR ? 1 : 0, +	       regs->msr & MSR_FP ? 1 : 0,regs->msr & MSR_ME ? 1 : 0, +	       regs->msr & MSR_IR ? 1 : 0, +	       regs->msr & MSR_DR ? 1 : 0); + +	putc('\n'); +	for (i = 0;  i < 32;  i++) { +		if ((i % 8) == 0) { +			printf("GPR%02d: ", i); +		} + +		printf("%08lX ", regs->gpr[i]); +		if ((i % 8) == 7) { +			putc('\n'); +		} +	} +} + + +static void _exception(int signr, struct pt_regs *regs) +{ +	show_regs(regs); +	print_backtrace((unsigned long *)regs->gpr[1]); +	panic("Exception at pc %lx signal %d", regs->nip, signr); +} + + +void MachineCheckException(struct pt_regs *regs) +{ +	unsigned long fixup = search_exception_table(regs->nip); + +	if (fixup) { +		regs->nip = fixup; +		return; +	} + +#ifdef CONFIG_CMD_KGDB +	if (debugger_exception_handler && (*debugger_exception_handler)(regs)) +		return; +#endif + +	puts("Machine check.\nCaused by (from msr): "); +	printf("regs %p ", regs); +	switch (regs->msr & 0x00FF0000) { +	case (0x80000000 >> 10): +		puts("Instruction cache parity signal\n"); +		break; +	case (0x80000000 >> 11): +		puts("Data cache parity signal\n"); +		break; +	case (0x80000000 >> 12): +		puts("Machine check signal\n"); +		break; +	case (0x80000000 >> 13): +		puts("Transfer error ack signal\n"); +		break; +	case (0x80000000 >> 14): +		puts("Data parity signal\n"); +		break; +	case (0x80000000 >> 15): +		puts("Address parity signal\n"); +		break; +	default: +		puts("Unknown values in msr\n"); +	} +	show_regs(regs); +	print_backtrace((unsigned long *)regs->gpr[1]); + +	panic("machine check"); +} + +void AlignmentException(struct pt_regs *regs) +{ +#ifdef CONFIG_CMD_KGDB +	if (debugger_exception_handler && (*debugger_exception_handler)(regs)) +		return; +#endif +	show_regs(regs); +	print_backtrace((unsigned long *)regs->gpr[1]); +	panic("Alignment Exception"); +} + +void ProgramCheckException(struct pt_regs *regs) +{ +#ifdef CONFIG_CMD_KGDB +	if (debugger_exception_handler && (*debugger_exception_handler)(regs)) +		return; +#endif +	show_regs(regs); +	print_backtrace((unsigned long *)regs->gpr[1]); +	panic("Program Check Exception"); +} + +void SoftEmuException(struct pt_regs *regs) +{ +#ifdef CONFIG_CMD_KGDB +	if (debugger_exception_handler && (*debugger_exception_handler)(regs)) +		return; +#endif +	show_regs(regs); +	print_backtrace((unsigned long *)regs->gpr[1]); +	panic("Software Emulation Exception"); +} + + +void UnknownException(struct pt_regs *regs) +{ +#ifdef CONFIG_CMD_KGDB +	if (debugger_exception_handler && (*debugger_exception_handler)(regs)) +		return; +#endif +	printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n", +	       regs->nip, regs->msr, regs->trap); +	_exception(0, regs); +} + +#ifdef CONFIG_CMD_BEDBUG +extern void do_bedbug_breakpoint(struct pt_regs *); +#endif + +void DebugException(struct pt_regs *regs) +{ +	printf("Debugger trap at @ %lx\n", regs->nip); +	show_regs(regs); +#ifdef CONFIG_CMD_BEDBUG +	do_bedbug_breakpoint(regs); +#endif +} diff --git a/roms/u-boot/arch/powerpc/cpu/mpc512x/u-boot.lds b/roms/u-boot/arch/powerpc/cpu/mpc512x/u-boot.lds new file mode 100644 index 00000000..9658b219 --- /dev/null +++ b/roms/u-boot/arch/powerpc/cpu/mpc512x/u-boot.lds @@ -0,0 +1,74 @@ +/* + * (C) Copyright 2007-2010 DENX Software Engineering. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +OUTPUT_ARCH(powerpc) +SECTIONS +{ +  .text      : +  { +    arch/powerpc/cpu/mpc512x/start.o	(.text*) +    *(.text*) +    . = ALIGN(16); +    *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) +  } + +  /* Read-write section, merged into data segment: */ +  . = (. + 0x0FFF) & 0xFFFFF000; +  _erotext = .; +  PROVIDE (erotext = .); +  .reloc   : +  { +    _GOT2_TABLE_ = .; +    KEEP(*(.got2)) +    KEEP(*(.got)) +    PROVIDE(_GLOBAL_OFFSET_TABLE_ = . + 4); +    _FIXUP_TABLE_ = .; +    KEEP(*(.fixup)) +    *(.fixup) +  } +  __got2_entries = ((_GLOBAL_OFFSET_TABLE_ - _GOT2_TABLE_) >> 2) - 1; +  __fixup_entries = (. - _FIXUP_TABLE_) >> 2; + +  .data    : +  { +    *(.data*) +    *(.sdata*) +  } +  _edata  =  .; +  PROVIDE (edata = .); + +  . = .; + +  . = ALIGN(4); +  .u_boot_list : { +	KEEP(*(SORT(.u_boot_list*))); +  } + + +  . = .; +  __start___ex_table = .; +  __ex_table : { *(__ex_table) } +  __stop___ex_table = .; + +  . = ALIGN(4096); +  __init_begin = .; +  .text.init : { *(.text.init) } +  .data.init : { *(.data.init) } +  . = ALIGN(4096); +  __init_end = .; + +  __bss_start = .; +  .bss (NOLOAD)       : +  { +   *(.bss*) +   *(.sbss*) +   *(COMMON) +   . = ALIGN(4); +  } +  __bss_end = . ; +  PROVIDE (end = .); +} +ENTRY(_start)  | 
