diff options
Diffstat (limited to 'board/mpc8349itx')
| -rw-r--r-- | board/mpc8349itx/Makefile | 48 | ||||
| -rw-r--r-- | board/mpc8349itx/config.mk | 33 | ||||
| -rw-r--r-- | board/mpc8349itx/mpc8349itx.c | 477 | ||||
| -rw-r--r-- | board/mpc8349itx/pci.c | 357 | ||||
| -rw-r--r-- | board/mpc8349itx/u-boot.lds | 120 | 
5 files changed, 1035 insertions, 0 deletions
| diff --git a/board/mpc8349itx/Makefile b/board/mpc8349itx/Makefile new file mode 100644 index 000000000..31bcdb864 --- /dev/null +++ b/board/mpc8349itx/Makefile @@ -0,0 +1,48 @@ +# +# Copyright (C) Freescale Semiconductor, Inc. 2006. All rights reserved. +# +# 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 $(TOPDIR)/config.mk + +LIB	= $(obj)lib$(BOARD).a + +COBJS	:= $(BOARD).o pci.o + +SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS	:= $(addprefix $(obj),$(COBJS)) +SOBJS	:= $(addprefix $(obj),$(SOBJS)) + +$(LIB):	$(obj).depend $(OBJS) +	$(AR) crv $@ $(OBJS) + +clean: +	rm -f $(SOBJS) $(OBJS) + +distclean:	clean +	rm -f $(LIB) core *.bak .depend + +######################################################################### + +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/mpc8349itx/config.mk b/board/mpc8349itx/config.mk new file mode 100644 index 000000000..2e113118b --- /dev/null +++ b/board/mpc8349itx/config.mk @@ -0,0 +1,33 @@ +# +# Copyright (C) Freescale Semiconductor, Inc. 2006. All rights reserved. +# +# 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 +# + +# +# MPC8349ITX +# + +TEXT_BASE  =   0xFEF00000 + +ifneq ($(OBJTREE),$(SRCTREE)) +# We are building u-boot in a separate directory, use generated +# .lds script from OBJTREE directory. +LDSCRIPT := $(OBJTREE)/board/$(BOARDDIR)/u-boot.lds +endif diff --git a/board/mpc8349itx/mpc8349itx.c b/board/mpc8349itx/mpc8349itx.c new file mode 100644 index 000000000..4838e707f --- /dev/null +++ b/board/mpc8349itx/mpc8349itx.c @@ -0,0 +1,477 @@ +/* + * Copyright (C) Freescale Semiconductor, Inc. 2006. All rights reserved. + * + * 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 <ioports.h> +#include <mpc83xx.h> +#include <i2c.h> +#include <spd.h> +#include <miiphy.h> + +#ifdef CONFIG_PCI +#include <asm/mpc8349_pci.h> +#include <pci.h> +#endif + +#ifdef CONFIG_SPD_EEPROM +#include <spd_sdram.h> +#else +#include <asm/mmu.h> +#endif +#if defined(CONFIG_OF_FLAT_TREE) +#include <ft_build.h> +#endif + +#ifndef CONFIG_SPD_EEPROM +/************************************************************************* + *  fixed sdram init -- doesn't use serial presence detect. + ************************************************************************/ +int fixed_sdram(void) +{ +	volatile immap_t *im = (immap_t *) CFG_IMMR; +	u32 ddr_size;		/* The size of RAM, in bytes */ +	u32 ddr_size_log2 = 0; + +	for (ddr_size = CFG_DDR_SIZE * 0x100000; ddr_size > 1; ddr_size >>= 1) { +		if (ddr_size & 1) { +			return -1; +		} +		ddr_size_log2++; +	} + +	im->sysconf.ddrlaw[0].ar = +	    LAWAR_EN | ((ddr_size_log2 - 1) & LAWAR_SIZE); +	im->sysconf.ddrlaw[0].bar = (CFG_DDR_SDRAM_BASE >> 12) & 0xfffff; + +	/* Only one CS0 for DDR */ +	im->ddr.csbnds[0].csbnds = 0x0000000f; +	im->ddr.cs_config[0] = CFG_DDR_CONFIG; + +	debug("cs0_bnds = 0x%08x\n", im->ddr.csbnds[0].csbnds); +	debug("cs0_config = 0x%08x\n", im->ddr.cs_config[0]); + +	debug("DDR:bar=0x%08x\n", im->sysconf.ddrlaw[0].bar); +	debug("DDR:ar=0x%08x\n", im->sysconf.ddrlaw[0].ar); + +	im->ddr.timing_cfg_1 = CFG_DDR_TIMING_1; +	im->ddr.timing_cfg_2 = CFG_DDR_TIMING_2;/* Was "2 << TIMING_CFG2_WR_DATA_DELAY_SHIFT" */ +	im->ddr.sdram_cfg = SDRAM_CFG_SREN | SDRAM_CFG_SDRAM_TYPE_DDR; +	im->ddr.sdram_mode = +	    (0x0000 << SDRAM_MODE_ESD_SHIFT) | (0x0032 << SDRAM_MODE_SD_SHIFT); +	im->ddr.sdram_interval = +	    (0x0410 << SDRAM_INTERVAL_REFINT_SHIFT) | (0x0100 << +						       SDRAM_INTERVAL_BSTOPRE_SHIFT); +	im->ddr.sdram_clk_cntl = +	    DDR_SDRAM_CLK_CNTL_SS_EN | DDR_SDRAM_CLK_CNTL_CLK_ADJUST_05; + +	udelay(200); + +	im->ddr.sdram_cfg |= SDRAM_CFG_MEM_EN; + +	debug("DDR:timing_cfg_1=0x%08x\n", im->ddr.timing_cfg_1); +	debug("DDR:timing_cfg_2=0x%08x\n", im->ddr.timing_cfg_2); +	debug("DDR:sdram_mode=0x%08x\n", im->ddr.sdram_mode); +	debug("DDR:sdram_interval=0x%08x\n", im->ddr.sdram_interval); +	debug("DDR:sdram_cfg=0x%08x\n", im->ddr.sdram_cfg); + +	return CFG_DDR_SIZE; +} +#endif + +#ifdef CONFIG_PCI +/* + * Initialize PCI Devices, report devices found + */ +#ifndef CONFIG_PCI_PNP +static struct pci_config_table pci_mpc83xxmitx_config_table[] = { +	{ +	 PCI_ANY_ID, +	 PCI_ANY_ID, +	 PCI_ANY_ID, +	 PCI_ANY_ID, +	 0x0f, +	 PCI_ANY_ID, +	 pci_cfgfunc_config_device, +	 { +	  PCI_ENET0_IOADDR, +	  PCI_ENET0_MEMADDR, +	  PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER} +	 }, +	{} +} +#endif + +volatile static struct pci_controller hose[] = { +	{ +#ifndef CONFIG_PCI_PNP +	      config_table:pci_mpc83xxmitx_config_table, +#endif +	 }, +	{ +#ifndef CONFIG_PCI_PNP +	      config_table:pci_mpc83xxmitx_config_table, +#endif +	 } +}; +#endif				/* CONFIG_PCI */ + +/* If MPC8349E-mITX is soldered with SDRAM, then initialize it. */ + +void sdram_init(void) +{ +	volatile immap_t *immap = (immap_t *) CFG_IMMR; +	volatile lbus83xx_t *lbc = &immap->lbus; + +#if defined(CFG_BR2_PRELIM) \ +	&& defined(CFG_OR2_PRELIM) \ +	&& defined(CFG_LBLAWBAR2_PRELIM) \ +	&& defined(CFG_LBLAWAR2_PRELIM) \ +	&& !defined(CONFIG_COMPACT_FLASH) + +	uint *sdram_addr = (uint *) CFG_LBC_SDRAM_BASE; + +	puts("\n   SDRAM on Local Bus: "); +	print_size(CFG_LBC_SDRAM_SIZE * 1024 * 1024, "\n"); + +	/* +	 * Setup SDRAM Base and Option Registers, already done in cpu_init.c +	 */ + +	/*setup mtrpt, lsrt and lbcr for LB bus */ +	lbc->lbcr = CFG_LBC_LBCR; +	lbc->mrtpr = CFG_LBC_MRTPR; +	lbc->lsrt = CFG_LBC_LSRT; +	asm("sync"); + +	/* +	 * Configure the SDRAM controller Machine Mode register. +	 */ +	lbc->lsdmr = CFG_LBC_LSDMR_5;	/* 0x40636733; normal operation */ + +	lbc->lsdmr = CFG_LBC_LSDMR_1;	/*0x68636733; precharge all the banks */ +	asm("sync"); +	*sdram_addr = 0xff; +	udelay(100); + +	lbc->lsdmr = CFG_LBC_LSDMR_2;	/*0x48636733; auto refresh */ +	asm("sync"); +	*sdram_addr = 0xff; /*1 time*/ +	udelay(100); +	*sdram_addr = 0xff; /*2 times*/ +	udelay(100); +	*sdram_addr = 0xff; /*3 times*/ +	udelay(100); +	*sdram_addr = 0xff; /*4 times*/ +	udelay(100); +	*sdram_addr = 0xff; /*5 times*/ +	udelay(100); +	*sdram_addr = 0xff; /*6 times*/ +	udelay(100); +	*sdram_addr = 0xff; /*7 times*/ +	udelay(100); +	*sdram_addr = 0xff; /*8 times*/ +	udelay(100); + +	lbc->lsdmr = CFG_LBC_LSDMR_4;	/*0x58636733;mode register write operation */ +	asm("sync"); +	*sdram_addr = 0xff; +	udelay(100); + +	lbc->lsdmr = CFG_LBC_LSDMR_5;	/*0x40636733;normal operation */ +	asm("sync"); +	*sdram_addr = 0xff; +	udelay(100); + +#else +	puts("SDRAM on Local Bus is NOT available!\n"); + +#ifdef CFG_BR2_PRELIM +	lbc->bank[2].br = CFG_BR2_PRELIM; +	lbc->bank[2].or = CFG_OR2_PRELIM; +#endif + +#ifdef CFG_BR3_PRELIM +	lbc->bank[3].br = CFG_BR3_PRELIM; +	lbc->bank[3].or = CFG_OR3_PRELIM; +#endif +#endif +} + +long int initdram(int board_type) +{ +	volatile immap_t *im = (immap_t *) CFG_IMMR; +	u32 msize = 0; +#ifdef CONFIG_DDR_ECC +	volatile ddr83xx_t *ddr = &im->ddr; +#endif + +	if ((im->sysconf.immrbar & IMMRBAR_BASE_ADDR) != (u32) im) +		return -1; + +	/* DDR SDRAM - Main SODIMM */ +	im->sysconf.ddrlaw[0].bar = CFG_DDR_BASE & LAWBAR_BAR; +#ifdef CONFIG_SPD_EEPROM +	msize = spd_sdram(); +#else +	msize = fixed_sdram(); +#endif + +#ifdef CONFIG_DDR_ECC +	if (ddr->sdram_cfg & SDRAM_CFG_ECC_EN) +		/* Unlike every other board, on the 83xx spd_sdram() returns +		   megabytes instead of just bytes.  That's why we need to +		   multiple by 1MB when calling ddr_enable_ecc(). */ +		ddr_enable_ecc(msize * 1048576); +#endif + +	/* +	 * Initialize SDRAM if it is on local bus. +	 */ +	sdram_init(); +	puts("   DDR RAM: "); +	/* return total bus SDRAM size(bytes)  -- DDR */ +	return msize * 1024 * 1024; +} + +int checkboard(void) +{ +	puts("Board: Freescale MPC8349E-mITX\n"); + +	return 0; +} + +/* + * Implement a work-around for a hardware problem with compact + * flash. + * + * Program the UPM if compact flash is enabled. + */ +int misc_init_f(void) +{ +	volatile u32 *vsc7385_cpuctrl; + +	/* 0x1c0c0 is the VSC7385 CPU Control (CPUCTRL) Register.  The power up +	   default of VSC7385 L1_IRQ and L2_IRQ requests are active high.  That +	   means it is 0 when the IRQ is not active.  This makes the wire-AND +	   logic always assert IRQ7 to CPU even if there is no request from the +	   switch.  Since the compact flash and the switch share the same IRQ, +	   the Linux kernel will think that the compact flash is requesting irq +	   and get stuck when it tries to clear the IRQ.  Thus we need to set +	   the L2_IRQ0 and L2_IRQ1 to active low. + +	   The following code sets the L1_IRQ and L2_IRQ polarity to active low. +	   Without this code, compact flash will not work in Linux because +	   unlike U-Boot, Linux uses the IRQ, so this code is necessary if we +	   don't enable compact flash for U-Boot. +	 */ + +	vsc7385_cpuctrl = (volatile u32 *)(CFG_VSC7385_BASE + 0x1c0c0); +	*vsc7385_cpuctrl |= 0x0c; + +#ifdef CONFIG_COMPACT_FLASH +	/* UPM Table Configuration Code */ +	static uint UPMATable[] = { +		0xcffffc00, 0x0fffff00, 0x0fafff00, 0x0fafff00, +		0x0faffd00, 0x0faffc04, 0x0ffffc00, 0x3ffffc01, +		0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, +		0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, +		0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfff7fc00, +		0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01, +		0xcffffc00, 0x0fffff00, 0x0ff3ff00, 0x0ff3ff00, +		0x0ff3fe00, 0x0ffffc00, 0x3ffffc05, 0xfffffc00, +		0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, +		0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, +		0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, +		0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01, +		0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, +		0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00, +		0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01, +		0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01 +	}; +	volatile immap_t *immap = (immap_t *) CFG_IMMR; +	volatile lbus83xx_t *lbus = &immap->lbus; + +	lbus->bank[3].br = CFG_BR3_PRELIM; +	lbus->bank[3].or = CFG_OR3_PRELIM; + +	/* Program the MAMR. RFEN=0, OP=00, UWPL=1, AM=000, DS=01, G0CL=000, +	   GPL4=0, RLF=0001, WLF=0001, TLF=0001, MAD=000000 +	 */ +	lbus->mamr = 0x08404440; + +	upmconfig(0, UPMATable, sizeof(UPMATable) / sizeof(UPMATable[0])); + +	puts("UPMA:  Configured for compact flash\n"); +#endif + +	return 0; +} + +/* + * Make sure the EEPROM has the HRCW correctly programmed. + * Make sure the RTC is correctly programmed. + * + * The MPC8349E-mITX can be configured to load the HRCW from + * EEPROM instead of flash.  This is controlled via jumpers + * LGPL0, 1, and 3.  Normally, these jumpers are set to 000 (all + * jumpered), but if they're set to 001 or 010, then the HRCW is + * read from the "I2C EEPROM". + * + * This function makes sure that the I2C EEPROM is programmed + * correctly. + */ +int misc_init_r(void) +{ +	int rc = 0; + +#ifdef CONFIG_HARD_I2C + +	unsigned int orig_bus = i2c_get_bus_num();; +	u8 i2c_data; + +#ifdef CFG_I2C_RTC_ADDR +	u8 ds1339_data[17]; +#endif + +#ifdef CFG_I2C_EEPROM_ADDR +	static u8 eeprom_data[] =	/* HRCW data */ +	{ +		0xaa, 0x55, 0xaa, +		0x7c, 0x02, 0x40, 0x05, 0x04, 0x00, 0x00, +		0x7c, 0x02, 0x41, 0xb4, 0x60, 0xa0, 0x00, +	}; + +	u8 data[sizeof(eeprom_data)]; +#endif + +	printf("Board revision: "); +	i2c_set_bus_num(1); +	if (i2c_read(CFG_I2C_8574A_ADDR2, 0, 0, &i2c_data, sizeof(i2c_data)) == 0) +		printf("%u.%u (PCF8475A)\n", (i2c_data & 0x02) >> 1, i2c_data & 0x01); +	else if (i2c_read(CFG_I2C_8574_ADDR2, 0, 0, &i2c_data, sizeof(i2c_data)) == 0) +		printf("%u.%u (PCF8475)\n",  (i2c_data & 0x02) >> 1, i2c_data & 0x01); +	else { +		printf("Unknown\n"); +		rc = 1; +	} + +#ifdef CFG_I2C_EEPROM_ADDR +	i2c_set_bus_num(0); + +	if (i2c_read(CFG_I2C_EEPROM_ADDR, 0, 2, data, sizeof(data)) == 0) { +		if (memcmp(data, eeprom_data, sizeof(data)) != 0) { +			if (i2c_write +			    (CFG_I2C_EEPROM_ADDR, 0, 2, eeprom_data, +			     sizeof(eeprom_data)) != 0) { +				puts("Failure writing the HRCW to EEPROM via I2C.\n"); +				rc = 1; +			} +		} +	} else { +		puts("Failure reading the HRCW from EEPROM via I2C.\n"); +		rc = 1; +	} +#endif + +#ifdef CFG_I2C_RTC_ADDR +	i2c_set_bus_num(1); + +	if (i2c_read(CFG_I2C_RTC_ADDR, 0, 1, ds1339_data, sizeof(ds1339_data)) +	    == 0) { + +		/* Work-around for MPC8349E-mITX bug #13601. +		   If the RTC does not contain valid register values, the DS1339 +		   Linux driver will not work. +		 */ + +		/* Make sure status register bits 6-2 are zero */ +		ds1339_data[0x0f] &= ~0x7c; + +		/* Check for a valid day register value */ +		ds1339_data[0x03] &= ~0xf8; +		if (ds1339_data[0x03] == 0) { +			ds1339_data[0x03] = 1; +		} + +		/* Check for a valid date register value */ +		ds1339_data[0x04] &= ~0xc0; +		if ((ds1339_data[0x04] == 0) || +		    ((ds1339_data[0x04] & 0x0f) > 9) || +		    (ds1339_data[0x04] >= 0x32)) { +			ds1339_data[0x04] = 1; +		} + +		/* Check for a valid month register value */ +		ds1339_data[0x05] &= ~0x60; + +		if ((ds1339_data[0x05] == 0) || +		    ((ds1339_data[0x05] & 0x0f) > 9) || +		    ((ds1339_data[0x05] >= 0x13) +		     && (ds1339_data[0x05] <= 0x19))) { +			ds1339_data[0x05] = 1; +		} + +		/* Enable Oscillator and rate select */ +		ds1339_data[0x0e] = 0x1c; + +		/* Work-around for MPC8349E-mITX bug #13330. +		   Ensure that the RTC control register contains the value 0x1c. +		   This affects SATA performance. +		 */ + +		if (i2c_write +		    (CFG_I2C_RTC_ADDR, 0, 1, ds1339_data, +		     sizeof(ds1339_data))) { +			puts("Failure writing to the RTC via I2C.\n"); +			rc = 1; +		} +	} else { +		puts("Failure reading from the RTC via I2C.\n"); +		rc = 1; +	} +#endif + +	i2c_set_bus_num(orig_bus); +#endif + +	return rc; +} + +#if defined(CONFIG_OF_FLAT_TREE) && defined(CONFIG_OF_BOARD_SETUP) +void +ft_board_setup(void *blob, bd_t *bd) +{ +	u32 *p; +	int len; + +#ifdef CONFIG_PCI +	ft_pci_setup(blob, bd); +#endif +	ft_cpu_setup(blob, bd); + +	p = ft_get_prop(blob, "/memory/reg", &len); +	if (p != NULL) { +		*p++ = cpu_to_be32(bd->bi_memstart); +		*p = cpu_to_be32(bd->bi_memsize); +	} +} +#endif diff --git a/board/mpc8349itx/pci.c b/board/mpc8349itx/pci.c new file mode 100644 index 000000000..e81ad2735 --- /dev/null +++ b/board/mpc8349itx/pci.c @@ -0,0 +1,357 @@ +/* + * Copyright (C) Freescale Semiconductor, Inc. 2006. All rights reserved. + * + * 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> + +#ifdef CONFIG_PCI + +#include <asm/mmu.h> +#include <asm/global_data.h> +#include <pci.h> +#include <asm/mpc8349_pci.h> +#include <i2c.h> +#if defined(CONFIG_OF_FLAT_TREE) +#include <ft_build.h> +#endif + +DECLARE_GLOBAL_DATA_PTR; + +/* System RAM mapped to PCI space */ +#define CONFIG_PCI_SYS_MEM_BUS	CFG_SDRAM_BASE +#define CONFIG_PCI_SYS_MEM_PHYS	CFG_SDRAM_BASE + +#ifndef CONFIG_PCI_PNP +static struct pci_config_table pci_mpc8349itx_config_table[] = { +	{ +	 PCI_ANY_ID, +	 PCI_ANY_ID, +	 PCI_ANY_ID, +	 PCI_ANY_ID, +	 PCI_IDSEL_NUMBER, +	 PCI_ANY_ID, +	 pci_cfgfunc_config_device, +	 { +	  PCI_ENET0_IOADDR, +	  PCI_ENET0_MEMADDR, +	  PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER} +	 }, +	{} +}; +#endif + +static struct pci_controller pci_hose[] = { +	{ +#ifndef CONFIG_PCI_PNP +	      config_table:pci_mpc8349itx_config_table, +#endif +	 }, +	{ +#ifndef CONFIG_PCI_PNP +	      config_table:pci_mpc8349itx_config_table, +#endif +	 } +}; + +/************************************************************************** + * pci_init_board() + * + * NOTICE: PCI2 is not currently supported + * + */ +void pci_init_board(void) +{ +	volatile immap_t *immr; +	volatile clk83xx_t *clk; +	volatile law83xx_t *pci_law; +	volatile pot83xx_t *pci_pot; +	volatile pcictrl83xx_t *pci_ctrl; +	volatile pciconf83xx_t *pci_conf; +	u8 reg8; +	u16 reg16; +	u32 reg32; +	u32 dev; +	struct pci_controller *hose; + +	immr = (immap_t *) CFG_IMMR; +	clk = (clk83xx_t *) & immr->clk; +	pci_law = immr->sysconf.pcilaw; +	pci_pot = immr->ios.pot; +	pci_ctrl = immr->pci_ctrl; +	pci_conf = immr->pci_conf; + +	hose = &pci_hose[0]; + +	/* +	 * Configure PCI controller and PCI_CLK_OUTPUT both in 66M mode +	 */ + +	reg32 = clk->occr; +	udelay(2000); + +#ifdef CONFIG_HARD_I2C +	i2c_set_bus_num(1); +	/* Read the PCI_M66EN jumper setting */ +	if ((i2c_read(CFG_I2C_8574_ADDR2, 0, 0, ®8, sizeof(reg8)) == 0) || +	    (i2c_read(CFG_I2C_8574A_ADDR2, 0, 0, ®8, sizeof(reg8)) == 0)) { +		if (reg8 & I2C_8574_PCI66) +			clk->occr = 0xff000000;	/* 66 MHz PCI */ +		else +			clk->occr = 0xff600001;	/* 33 MHz PCI */ +	} else { +		clk->occr = 0xff600001;	/* 33 MHz PCI */ +	} +#else +	clk->occr = 0xff000000;	/* 66 MHz PCI */ +#endif + +	udelay(2000); + +	/* +	 * Release PCI RST Output signal +	 */ +	pci_ctrl[0].gcr = 0; +	udelay(2000); +	pci_ctrl[0].gcr = 1; + +#ifdef CONFIG_MPC83XX_PCI2 +	pci_ctrl[1].gcr = 0; +	udelay(2000); +	pci_ctrl[1].gcr = 1; +#endif + +	/* We need to wait at least a 1sec based on PCI specs */ +	{ +		int i; + +		for (i = 0; i < 1000; i++) +			udelay(1000); +	} + +	/* +	 * Configure PCI Local Access Windows +	 */ +	pci_law[0].bar = CFG_PCI1_MEM_PHYS & LAWBAR_BAR; +	pci_law[0].ar = LAWAR_EN | LAWAR_SIZE_1G; + +	pci_law[1].bar = CFG_PCI1_IO_PHYS & LAWBAR_BAR; +	pci_law[1].ar = LAWAR_EN | LAWAR_SIZE_32M; + +	/* +	 * Configure PCI Outbound Translation Windows +	 */ + +	/* PCI1 mem space - prefetch */ +	pci_pot[0].potar = (CFG_PCI1_MEM_BASE >> 12) & POTAR_TA_MASK; +	pci_pot[0].pobar = (CFG_PCI1_MEM_PHYS >> 12) & POBAR_BA_MASK; +	pci_pot[0].pocmr = POCMR_EN | POCMR_PREFETCH_EN | POCMR_CM_256M; + +	/* PCI1 IO space */ +	pci_pot[1].potar = (CFG_PCI1_IO_BASE >> 12) & POTAR_TA_MASK; +	pci_pot[1].pobar = (CFG_PCI1_IO_PHYS >> 12) & POBAR_BA_MASK; +	pci_pot[1].pocmr = POCMR_EN | POCMR_IO | POCMR_CM_16M; + +	/* PCI1 mmio - non-prefetch mem space */ +	pci_pot[2].potar = (CFG_PCI1_MMIO_BASE >> 12) & POTAR_TA_MASK; +	pci_pot[2].pobar = (CFG_PCI1_MMIO_PHYS >> 12) & POBAR_BA_MASK; +	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 */ +	pci_ctrl[0].pitar1 = 0x0; +	pci_ctrl[0].pibar1 = 0x0; +	pci_ctrl[0].piebar1 = 0x0; +	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, +		       CFG_PCI1_MEM_BASE, +		       CFG_PCI1_MEM_PHYS, +		       CFG_PCI1_MEM_SIZE, PCI_REGION_MEM | PCI_REGION_PREFETCH); + +	/* PCI memory space */ +	pci_set_region(hose->regions + 1, +		       CFG_PCI1_MMIO_BASE, +		       CFG_PCI1_MMIO_PHYS, CFG_PCI1_MMIO_SIZE, PCI_REGION_MEM); + +	/* PCI IO space */ +	pci_set_region(hose->regions + 2, +		       CFG_PCI1_IO_BASE, +		       CFG_PCI1_IO_PHYS, CFG_PCI1_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_MEMORY); + +	hose->region_count = 4; + +	pci_setup_indirect(hose, +			   (CFG_IMMR + 0x8300), (CFG_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); + +#ifdef CONFIG_MPC83XX_PCI2 +	hose = &pci_hose[1]; + +	/* +	 * Configure PCI Outbound Translation Windows +	 */ + +	/* PCI2 mem space - prefetch */ +	pci_pot[3].potar = (CFG_PCI2_MEM_BASE >> 12) & POTAR_TA_MASK; +	pci_pot[3].pobar = (CFG_PCI2_MEM_PHYS >> 12) & POBAR_BA_MASK; +	pci_pot[3].pocmr = POCMR_EN | POCMR_PCI2 | POCMR_PREFETCH_EN | POCMR_CM_256M; + +	/* PCI2 IO space */ +	pci_pot[4].potar = (CFG_PCI2_IO_BASE >> 12) & POTAR_TA_MASK; +	pci_pot[4].pobar = (CFG_PCI2_IO_PHYS >> 12) & POBAR_BA_MASK; +	pci_pot[4].pocmr = POCMR_EN | POCMR_PCI2 | POCMR_IO | POCMR_CM_16M; + +	/* PCI2 mmio - non-prefetch mem space */ +	pci_pot[5].potar = (CFG_PCI2_MMIO_BASE >> 12) & POTAR_TA_MASK; +	pci_pot[5].pobar = (CFG_PCI2_MMIO_PHYS >> 12) & POBAR_BA_MASK; +	pci_pot[5].pocmr = POCMR_EN | POCMR_PCI2 | POCMR_CM_256M; + +	/* +	 * Configure PCI Inbound Translation Windows +	 */ + +	/* we need RAM mapped to PCI space for the devices to +	 * access main memory */ +	pci_ctrl[1].pitar1 = 0x0; +	pci_ctrl[1].pibar1 = 0x0; +	pci_ctrl[1].piebar1 = 0x0; +	pci_ctrl[1].piwar1 = +	    PIWAR_EN | PIWAR_PF | PIWAR_RTT_SNOOP | PIWAR_WTT_SNOOP | +	    (__ilog2(gd->ram_size) - 1); + +	hose->first_busno = pci_hose[0].last_busno + 1; +	hose->last_busno = 0xff; + +	/* PCI memory prefetch space */ +	pci_set_region(hose->regions + 0, +		       CFG_PCI2_MEM_BASE, +		       CFG_PCI2_MEM_PHYS, +		       CFG_PCI2_MEM_SIZE, PCI_REGION_MEM | PCI_REGION_PREFETCH); + +	/* PCI memory space */ +	pci_set_region(hose->regions + 1, +		       CFG_PCI2_MMIO_BASE, +		       CFG_PCI2_MMIO_PHYS, CFG_PCI2_MMIO_SIZE, PCI_REGION_MEM); + +	/* PCI IO space */ +	pci_set_region(hose->regions + 2, +		       CFG_PCI2_IO_BASE, +		       CFG_PCI2_IO_PHYS, CFG_PCI2_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_MEMORY); + +	hose->region_count = 4; + +	pci_setup_indirect(hose, +			   (CFG_IMMR + 0x8380), (CFG_IMMR + 0x8384)); + +	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); + +	/* +	 * Hose scan. +	 */ +	hose->last_busno = pci_hose_scan(hose); +#endif +} + +#endif				/* CONFIG_PCI */ +#ifdef CONFIG_OF_FLAT_TREE +void +ft_pci_setup(void *blob, bd_t *bd) +{ +       	u32 *p; +       	int len; + +       	p = (u32 *)ft_get_prop(blob, "/" OF_SOC "/pci@8500/bus-range", &len); +       	if (p != NULL) { +		p[0] = pci_hose[0].first_busno; +		p[1] = pci_hose[0].last_busno; +       	} + +#ifdef CONFIG_MPC83XX_PCI2 +	p = (u32 *)ft_get_prop(blob, "/" OF_SOC "/pci@8600/bus-range", &len); +	if (p != NULL) { +		p[0] = pci_hose[1].first_busno; +		p[1] = pci_hose[1].last_busno; +	} +#endif +} +#endif /* CONFIG_OF_FLAT_TREE */ diff --git a/board/mpc8349itx/u-boot.lds b/board/mpc8349itx/u-boot.lds new file mode 100644 index 000000000..f044c0f00 --- /dev/null +++ b/board/mpc8349itx/u-boot.lds @@ -0,0 +1,120 @@ +/* + * Copyright (C) Freescale Semiconductor, Inc. 2006. All rights reserved. + * + * 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 + */ + +OUTPUT_ARCH(powerpc) +SECTIONS +{ +  /* Read-only sections, merged into text segment: */ +  . = + SIZEOF_HEADERS; +  .interp : { *(.interp) } +  .hash          : { *(.hash)		} +  .dynsym        : { *(.dynsym)		} +  .dynstr        : { *(.dynstr)		} +  .rel.text      : { *(.rel.text)		} +  .rela.text     : { *(.rela.text) 	} +  .rel.data      : { *(.rel.data)		} +  .rela.data     : { *(.rela.data) 	} +  .rel.rodata    : { *(.rel.rodata) 	} +  .rela.rodata   : { *(.rela.rodata) 	} +  .rel.got       : { *(.rel.got)		} +  .rela.got      : { *(.rela.got)		} +  .rel.ctors     : { *(.rel.ctors)	} +  .rela.ctors    : { *(.rela.ctors)	} +  .rel.dtors     : { *(.rel.dtors)	} +  .rela.dtors    : { *(.rela.dtors)	} +  .rel.bss       : { *(.rel.bss)		} +  .rela.bss      : { *(.rela.bss)		} +  .rel.plt       : { *(.rel.plt)		} +  .rela.plt      : { *(.rela.plt)		} +  .init          : { *(.init)	} +  .plt : { *(.plt) } +  .text      : +  { +    cpu/mpc83xx/start.o	(.text) +    *(.text) +    *(.fixup) +    *(.got1) +    . = ALIGN(16); +    *(.rodata) +    *(.rodata1) +    *(.rodata.str1.4) +  } +  .fini      : { *(.fini)    } =0 +  .ctors     : { *(.ctors)   } +  .dtors     : { *(.dtors)   } + +  /* Read-write section, merged into data segment: */ +  . = (. + 0x0FFF) & 0xFFFFF000; +  _erotext = .; +  PROVIDE (erotext = .); +  .reloc   : +  { +    *(.got) +    _GOT2_TABLE_ = .; +    *(.got2) +    _FIXUP_TABLE_ = .; +    *(.fixup) +  } +  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2; +  __fixup_entries = (. - _FIXUP_TABLE_) >> 2; + +  .data    : +  { +    *(.data) +    *(.data1) +    *(.sdata) +    *(.sdata2) +    *(.dynamic) +    CONSTRUCTORS +  } +  _edata  =  .; +  PROVIDE (edata = .); + +  . = .; +  __u_boot_cmd_start = .; +  .u_boot_cmd : { *(.u_boot_cmd) } +  __u_boot_cmd_end = .; + +  . = .; +  __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       : +  { +   *(.sbss) *(.scommon) +   *(.dynbss) +   *(.bss) +   *(COMMON) +  } +  _end = . ; +  PROVIDE (end = .); +} +ENTRY(_start) |