diff options
Diffstat (limited to 'board/cpc45')
-rwxr-xr-x | board/cpc45/Makefile | 40 | ||||
-rwxr-xr-x | board/cpc45/config.mk | 36 | ||||
-rwxr-xr-x | board/cpc45/cpc45.c | 275 | ||||
-rwxr-xr-x | board/cpc45/flash.c | 522 | ||||
-rwxr-xr-x | board/cpc45/pd67290.c | 68 | ||||
-rwxr-xr-x | board/cpc45/plx9030.c | 173 | ||||
-rwxr-xr-x | board/cpc45/u-boot.lds | 136 |
7 files changed, 1250 insertions, 0 deletions
diff --git a/board/cpc45/Makefile b/board/cpc45/Makefile new file mode 100755 index 0000000..ccb811b --- /dev/null +++ b/board/cpc45/Makefile @@ -0,0 +1,40 @@ +# +# (C) Copyright 2001-2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = lib$(BOARD).a + +OBJS = $(BOARD).o flash.o plx9030.o pd67290.o + +$(LIB): .depend $(OBJS) + $(AR) crv $@ $(OBJS) + +######################################################################### + +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/board/cpc45/config.mk b/board/cpc45/config.mk new file mode 100755 index 0000000..bf9d9de --- /dev/null +++ b/board/cpc45/config.mk @@ -0,0 +1,36 @@ +# +# (C) Copyright 2001-2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +# +# CPC45 board +# + + +ifeq ($(CONFIG_BOOT_ROM),y) + TEXT_BASE := 0xFFF00000 + PLATFORM_CPPFLAGS += -DCONFIG_BOOT_ROM +else + TEXT_BASE := 0xFFF00000 +endif + +PLATFORM_CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE) -I$(TOPDIR) diff --git a/board/cpc45/cpc45.c b/board/cpc45/cpc45.c new file mode 100755 index 0000000..51b0085 --- /dev/null +++ b/board/cpc45/cpc45.c @@ -0,0 +1,275 @@ +/* + * (C) Copyright 2001 + * Rob Taylor, Flying Pig Systems. robt@flyingpig.com. + * + * 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 <mpc824x.h> +#include <asm/processor.h> +#include <asm/io.h> +#include <pci.h> +#include <i2c.h> + +int sysControlDisplay(int digit, uchar ascii_code); +extern void Plx9030Init(void); +extern void SPD67290Init(void); + + /* We have to clear the initial data area here. Couldn't have done it + * earlier because DRAM had not been initialized. + */ +int board_early_init_f(void) +{ + + /* enable DUAL UART Mode on CPC45 */ + *(uchar*)DUART_DCR |= 0x1; /* set DCM bit */ + + return 0; +} + +int checkboard(void) +{ +/* + char revision = BOARD_REV; +*/ + ulong busfreq = get_bus_freq(0); + char buf[32]; + + puts ("CPC45 "); +/* + printf("Revision %d ", revision); +*/ + printf("Local Bus at %s MHz\n", strmhz(buf, busfreq)); + + return 0; +} + +long int initdram (int board_type) +{ + int m, row, col, bank, i, ref; + unsigned long start, end; + uint32_t mccr1, mccr2; + uint32_t mear1 = 0, emear1 = 0, msar1 = 0, emsar1 = 0; + uint32_t mear2 = 0, emear2 = 0, msar2 = 0, emsar2 = 0; + uint8_t mber = 0; + unsigned int tmp; + + i2c_init(CFG_I2C_SPEED, CFG_I2C_SLAVE); + + if (i2c_reg_read (0x50, 2) != 0x04) + return 0; /* Memory type */ + + m = i2c_reg_read (0x50, 5); /* # of physical banks */ + row = i2c_reg_read (0x50, 3); /* # of rows */ + col = i2c_reg_read (0x50, 4); /* # of columns */ + bank = i2c_reg_read (0x50, 17); /* # of logical banks */ + ref = i2c_reg_read (0x50, 12); /* refresh rate / type */ + + CONFIG_READ_WORD(MCCR1, mccr1); + mccr1 &= 0xffff0000; + + CONFIG_READ_WORD(MCCR2, mccr2); + mccr2 &= 0xffff0000; + + start = CFG_SDRAM_BASE; + end = start + (1 << (col + row + 3) ) * bank - 1; + + for (i = 0; i < m; i++) { + mccr1 |= ((row == 13)? 2 : (bank == 4)? 0 : 3) << i * 2; + if (i < 4) { + msar1 |= ((start >> 20) & 0xff) << i * 8; + emsar1 |= ((start >> 28) & 0xff) << i * 8; + mear1 |= ((end >> 20) & 0xff) << i * 8; + emear1 |= ((end >> 28) & 0xff) << i * 8; + } else { + msar2 |= ((start >> 20) & 0xff) << (i-4) * 8; + emsar2 |= ((start >> 28) & 0xff) << (i-4) * 8; + mear2 |= ((end >> 20) & 0xff) << (i-4) * 8; + emear2 |= ((end >> 28) & 0xff) << (i-4) * 8; + } + mber |= 1 << i; + start += (1 << (col + row + 3) ) * bank; + end += (1 << (col + row + 3) ) * bank; + } + for (; i < 8; i++) { + if (i < 4) { + msar1 |= 0xff << i * 8; + emsar1 |= 0x30 << i * 8; + mear1 |= 0xff << i * 8; + emear1 |= 0x30 << i * 8; + } else { + msar2 |= 0xff << (i-4) * 8; + emsar2 |= 0x30 << (i-4) * 8; + mear2 |= 0xff << (i-4) * 8; + emear2 |= 0x30 << (i-4) * 8; + } + } + + switch(ref) { + case 0x00: + case 0x80: + tmp = get_bus_freq(0) / 1000000 * 15625 / 1000 - 22; + break; + case 0x01: + case 0x81: + tmp = get_bus_freq(0) / 1000000 * 3900 / 1000 - 22; + break; + case 0x02: + case 0x82: + tmp = get_bus_freq(0) / 1000000 * 7800 / 1000 - 22; + break; + case 0x03: + case 0x83: + tmp = get_bus_freq(0) / 1000000 * 31300 / 1000 - 22; + break; + case 0x04: + case 0x84: + tmp = get_bus_freq(0) / 1000000 * 62500 / 1000 - 22; + break; + case 0x05: + case 0x85: + tmp = get_bus_freq(0) / 1000000 * 125000 / 1000 - 22; + break; + default: + tmp = 0x512; + break; + } + + CONFIG_WRITE_WORD(MCCR1, mccr1); + CONFIG_WRITE_WORD(MCCR2, tmp << MCCR2_REFINT_SHIFT); + CONFIG_WRITE_WORD(MSAR1, msar1); + CONFIG_WRITE_WORD(EMSAR1, emsar1); + CONFIG_WRITE_WORD(MEAR1, mear1); + CONFIG_WRITE_WORD(EMEAR1, emear1); + CONFIG_WRITE_WORD(MSAR2, msar2); + CONFIG_WRITE_WORD(EMSAR2, emsar2); + CONFIG_WRITE_WORD(MEAR2, mear2); + CONFIG_WRITE_WORD(EMEAR2, emear2); + CONFIG_WRITE_BYTE(MBER, mber); + + return (1 << (col + row + 3) ) * bank * m; +} + + +/* + * Initialize PCI Devices, report devices found. + */ + +static struct pci_config_table pci_cpc45_config_table[] = { +#ifndef CONFIG_PCI_PNP + { 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 }}, + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x0D, PCI_ANY_ID, + pci_cfgfunc_config_device, { PCI_PLX9030_IOADDR, + PCI_PLX9030_MEMADDR, + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER }}, + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x0E, PCI_ANY_ID, + pci_cfgfunc_config_device, { PCMCIA_IO_BASE, + PCMCIA_IO_BASE, + PCI_COMMAND_MEMORY | PCI_COMMAND_IO }}, +#endif /*CONFIG_PCI_PNP*/ + { } +}; + +struct pci_controller hose = { +#ifndef CONFIG_PCI_PNP + config_table: pci_cpc45_config_table, +#endif +}; + +void pci_init_board(void) +{ + pci_mpc824x_init(&hose); + + /* init PCI_to_LOCAL Bus BRIDGE */ + Plx9030Init(); + + /* Clear Display */ + DISP_CWORD = 0x0; + + sysControlDisplay(0,' '); + sysControlDisplay(1,'C'); + sysControlDisplay(2,'P'); + sysControlDisplay(3,'C'); + sysControlDisplay(4,' '); + sysControlDisplay(5,'4'); + sysControlDisplay(6,'5'); + sysControlDisplay(7,' '); + +} + +/************************************************************************** +* +* sysControlDisplay - controls one of the Alphanum. Display digits. +* +* This routine will write an ASCII character to the display digit requested. +* +* SEE ALSO: +* +* RETURNS: NA +*/ + +int sysControlDisplay (int digit, /* number of digit 0..7 */ + uchar ascii_code /* ASCII code */ + ) +{ + if ((digit < 0) || (digit > 7)) + return (-1); + + *((volatile uchar *) (DISP_CHR_RAM + digit)) = ascii_code; + + return (0); +} + +#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA) + +#ifdef CFG_PCMCIA_MEM_ADDR +volatile unsigned char *pcmcia_mem = (unsigned char*)CFG_PCMCIA_MEM_ADDR; +#endif + +int pcmcia_init(void) +{ + u_int rc; + + debug ("Enable PCMCIA " PCMCIA_SLOT_MSG "\n"); + + rc = i82365_init(); + + return rc; +} + +#endif /* CFG_CMD_PCMCIA */ + +# ifdef CONFIG_IDE_LED +void ide_led (uchar led, uchar status) +{ + u_char val; + /* We have one PCMCIA slot and use LED H4 for the IDE Interface */ + val = readb(BCSR_BASE + 0x04); + if (status) { /* led on */ + val |= B_CTRL_LED0; + } else { + val &= ~B_CTRL_LED0; + } + writeb(val, BCSR_BASE + 0x04); +} +# endif diff --git a/board/cpc45/flash.c b/board/cpc45/flash.c new file mode 100755 index 0000000..37dd182 --- /dev/null +++ b/board/cpc45/flash.c @@ -0,0 +1,522 @@ +/* + * (C) Copyright 2001-2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <mpc824x.h> +#include <asm/processor.h> + +#if defined(CFG_ENV_IS_IN_FLASH) +# ifndef CFG_ENV_ADDR +# define CFG_ENV_ADDR (CFG_FLASH_BASE + CFG_ENV_OFFSET) +# endif +# ifndef CFG_ENV_SIZE +# define CFG_ENV_SIZE CFG_ENV_SECT_SIZE +# endif +# ifndef CFG_ENV_SECT_SIZE +# define CFG_ENV_SECT_SIZE CFG_ENV_SIZE +# endif +#endif + +#define FLASH_BANK_SIZE 0x800000 +#define MAIN_SECT_SIZE 0x40000 +#define PARAM_SECT_SIZE 0x8000 + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; + +static int write_data (flash_info_t * info, ulong dest, ulong * data); +static void write_via_fpu (vu_long * addr, ulong * data); +static __inline__ unsigned long get_msr (void); +static __inline__ void set_msr (unsigned long msr); + +/*---------------------------------------------------------------------*/ +#undef DEBUG_FLASH + +/*---------------------------------------------------------------------*/ +#ifdef DEBUG_FLASH +#define DEBUGF(fmt,args...) printf(fmt ,##args) +#else +#define DEBUGF(fmt,args...) +#endif +/*---------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------- + */ + +unsigned long flash_init (void) +{ + int i, j; + ulong size = 0; + uchar tempChar; + vu_long *tmpaddr; + + /* Enable flash writes on CPC45 */ + + tempChar = BOARD_CTRL; + + tempChar |= (B_CTRL_FWPT_1 | B_CTRL_FWRE_1); + + tempChar &= ~(B_CTRL_FWPT_0 | B_CTRL_FWRE_0); + + BOARD_CTRL = tempChar; + + __asm__ volatile ("sync\n eieio"); + + for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) { + vu_long *addr = (vu_long *) (CFG_FLASH_BASE + i * FLASH_BANK_SIZE); + + addr[0] = 0x00900090; + + __asm__ volatile ("sync\n eieio"); + + udelay (100); + + DEBUGF ("Flash bank # %d:\n" + "\tManuf. ID @ 0x%08lX: 0x%08lX\n" + "\tDevice ID @ 0x%08lX: 0x%08lX\n", + i, + (ulong) (&addr[0]), addr[0], + (ulong) (&addr[2]), addr[2]); + + + if ((addr[0] == addr[1]) && (addr[0] == INTEL_MANUFACT) && + (addr[2] == addr[3]) && (addr[2] == INTEL_ID_28F160F3T)) { + + flash_info[i].flash_id = + (FLASH_MAN_INTEL & FLASH_VENDMASK) | + (INTEL_ID_28F160F3T & FLASH_TYPEMASK); + + } else if ((addr[0] == addr[1]) && (addr[0] == INTEL_MANUFACT) + && (addr[2] == addr[3]) + && (addr[2] == INTEL_ID_28F160C3T)) { + + flash_info[i].flash_id = + (FLASH_MAN_INTEL & FLASH_VENDMASK) | + (INTEL_ID_28F160C3T & FLASH_TYPEMASK); + + } else { + flash_info[i].flash_id = FLASH_UNKNOWN; + addr[0] = 0xFFFFFFFF; + goto Done; + } + + DEBUGF ("flash_id = 0x%08lX\n", flash_info[i].flash_id); + + addr[0] = 0xFFFFFFFF; + + flash_info[i].size = FLASH_BANK_SIZE; + flash_info[i].sector_count = CFG_MAX_FLASH_SECT; + memset (flash_info[i].protect, 0, CFG_MAX_FLASH_SECT); + for (j = 0; j < flash_info[i].sector_count; j++) { + if (j > 30) { + flash_info[i].start[j] = CFG_FLASH_BASE + + i * FLASH_BANK_SIZE + + (MAIN_SECT_SIZE * 31) + (j - + 31) * + PARAM_SECT_SIZE; + } else { + flash_info[i].start[j] = CFG_FLASH_BASE + + i * FLASH_BANK_SIZE + + j * MAIN_SECT_SIZE; + } + } + + /* unlock sectors, if 160C3T */ + + for (j = 0; j < flash_info[i].sector_count; j++) { + tmpaddr = (vu_long *) flash_info[i].start[j]; + + if ((flash_info[i].flash_id & FLASH_TYPEMASK) == + (INTEL_ID_28F160C3T & FLASH_TYPEMASK)) { + tmpaddr[0] = 0x00600060; + tmpaddr[0] = 0x00D000D0; + tmpaddr[1] = 0x00600060; + tmpaddr[1] = 0x00D000D0; + } + } + + size += flash_info[i].size; + + addr[0] = 0x00FF00FF; + addr[1] = 0x00FF00FF; + } + + /* Protect monitor and environment sectors + */ +#if CFG_MONITOR_BASE >= CFG_FLASH_BASE + FLASH_BANK_SIZE + flash_protect (FLAG_PROTECT_SET, + CFG_MONITOR_BASE, + CFG_MONITOR_BASE + monitor_flash_len - 1, + &flash_info[1]); +#else + flash_protect (FLAG_PROTECT_SET, + CFG_MONITOR_BASE, + CFG_MONITOR_BASE + monitor_flash_len - 1, + &flash_info[0]); +#endif + +#if (CFG_ENV_IS_IN_FLASH == 1) && defined(CFG_ENV_ADDR) +#if CFG_ENV_ADDR >= CFG_FLASH_BASE + FLASH_BANK_SIZE + flash_protect (FLAG_PROTECT_SET, + CFG_ENV_ADDR, + CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[1]); +#else + flash_protect (FLAG_PROTECT_SET, + CFG_ENV_ADDR, + CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]); +#endif +#endif + +Done: + return size; +} + +/*----------------------------------------------------------------------- + */ +void flash_print_info (flash_info_t * info) +{ + int i; + + switch ((i = info->flash_id & FLASH_VENDMASK)) { + case (FLASH_MAN_INTEL & FLASH_VENDMASK): + printf ("Intel: "); + break; + default: + printf ("Unknown Vendor 0x%04x ", i); + break; + } + + switch ((i = info->flash_id & FLASH_TYPEMASK)) { + case (INTEL_ID_28F160F3T & FLASH_TYPEMASK): + printf ("28F160F3T (16Mbit)\n"); + break; + + case (INTEL_ID_28F160C3T & FLASH_TYPEMASK): + printf ("28F160C3T (16Mbit)\n"); + break; + + default: + printf ("Unknown Chip Type 0x%04x\n", i); + goto Done; + break; + } + + printf (" Size: %ld MB in %d Sectors\n", + info->size >> 20, info->sector_count); + + printf (" Sector Start Addresses:"); + for (i = 0; i < info->sector_count; i++) { + if ((i % 5) == 0) { + printf ("\n "); + } + printf (" %08lX%s", info->start[i], + info->protect[i] ? " (RO)" : " "); + } + printf ("\n"); + +Done: + return; +} + +/*----------------------------------------------------------------------- + */ + +int flash_erase (flash_info_t * info, int s_first, int s_last) +{ + int flag, prot, sect; + ulong start, now, last; + + DEBUGF ("Erase flash bank %d sect %d ... %d\n", + info - &flash_info[0], s_first, s_last); + + if ((s_first < 0) || (s_first > s_last)) { + if (info->flash_id == FLASH_UNKNOWN) { + printf ("- missing\n"); + } else { + printf ("- no sectors to erase\n"); + } + return 1; + } + + if ((info->flash_id & FLASH_VENDMASK) != + (FLASH_MAN_INTEL & FLASH_VENDMASK)) { + printf ("Can erase only Intel flash types - aborted\n"); + return 1; + } + + prot = 0; + for (sect = s_first; sect <= s_last; ++sect) { + if (info->protect[sect]) { + prot++; + } + } + + if (prot) { + printf ("- Warning: %d protected sectors will not be erased!\n", prot); + } else { + printf ("\n"); + } + + start = get_timer (0); + last = start; + /* Start erase on unprotected sectors */ + for (sect = s_first; sect <= s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + vu_long *addr = (vu_long *) (info->start[sect]); + + DEBUGF ("Erase sect %d @ 0x%08lX\n", + sect, (ulong) addr); + + /* Disable interrupts which might cause a timeout + * here. + */ + flag = disable_interrupts (); + + addr[0] = 0x00500050; /* clear status register */ + addr[0] = 0x00200020; /* erase setup */ + addr[0] = 0x00D000D0; /* erase confirm */ + + addr[1] = 0x00500050; /* clear status register */ + addr[1] = 0x00200020; /* erase setup */ + addr[1] = 0x00D000D0; /* erase confirm */ + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts (); + + /* wait at least 80us - let's wait 1 ms */ + udelay (1000); + + while (((addr[0] & 0x00800080) != 0x00800080) || + ((addr[1] & 0x00800080) != 0x00800080)) { + if ((now = get_timer (start)) > + CFG_FLASH_ERASE_TOUT) { + printf ("Timeout\n"); + addr[0] = 0x00B000B0; /* suspend erase */ + addr[0] = 0x00FF00FF; /* to read mode */ + return 1; + } + + /* show that we're waiting */ + if ((now - last) > 1000) { /* every second */ + putc ('.'); + last = now; + } + } + + addr[0] = 0x00FF00FF; + } + } + printf (" done\n"); + return 0; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + * 4 - Flash not identified + */ + +#define FLASH_WIDTH 8 /* flash bus width in bytes */ + +int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) +{ + ulong wp, cp, msr; + int l, rc, i; + ulong data[2]; + ulong *datah = &data[0]; + ulong *datal = &data[1]; + + DEBUGF ("Flash write_buff: @ 0x%08lx, src 0x%08lx len %ld\n", + addr, (ulong) src, cnt); + + if (info->flash_id == FLASH_UNKNOWN) { + return 4; + } + + msr = get_msr (); + set_msr (msr | MSR_FP); + + wp = (addr & ~(FLASH_WIDTH - 1)); /* get lower aligned address */ + + /* + * handle unaligned start bytes + */ + if ((l = addr - wp) != 0) { + *datah = *datal = 0; + + for (i = 0, cp = wp; i < l; i++, cp++) { + if (i >= 4) { + *datah = (*datah << 8) | + ((*datal & 0xFF000000) >> 24); + } + + *datal = (*datal << 8) | (*(uchar *) cp); + } + for (; i < FLASH_WIDTH && cnt > 0; ++i) { + char tmp = *src++; + + if (i >= 4) { + *datah = (*datah << 8) | + ((*datal & 0xFF000000) >> 24); + } + + *datal = (*datal << 8) | tmp; + --cnt; + ++cp; + } + + for (; cnt == 0 && i < FLASH_WIDTH; ++i, ++cp) { + if (i >= 4) { + *datah = (*datah << 8) | + ((*datal & 0xFF000000) >> 24); + } + + *datal = (*datah << 8) | (*(uchar *) cp); + } + + if ((rc = write_data (info, wp, data)) != 0) { + set_msr (msr); + return (rc); + } + + wp += FLASH_WIDTH; + } + + /* + * handle FLASH_WIDTH aligned part + */ + while (cnt >= FLASH_WIDTH) { + *datah = *(ulong *) src; + *datal = *(ulong *) (src + 4); + if ((rc = write_data (info, wp, data)) != 0) { + set_msr (msr); + return (rc); + } + wp += FLASH_WIDTH; + cnt -= FLASH_WIDTH; + src += FLASH_WIDTH; + } + + if (cnt == 0) { + set_msr (msr); + return (0); + } + + /* + * handle unaligned tail bytes + */ + *datah = *datal = 0; + for (i = 0, cp = wp; i < FLASH_WIDTH && cnt > 0; ++i, ++cp) { + char tmp = *src++; + + if (i >= 4) { + *datah = (*datah << 8) | ((*datal & 0xFF000000) >> + 24); + } + + *datal = (*datal << 8) | tmp; + --cnt; + } + + for (; i < FLASH_WIDTH; ++i, ++cp) { + if (i >= 4) { + *datah = (*datah << 8) | ((*datal & 0xFF000000) >> + 24); + } + + *datal = (*datal << 8) | (*(uchar *) cp); + } + + rc = write_data (info, wp, data); + set_msr (msr); + + return (rc); +} + +/*----------------------------------------------------------------------- + * Write a word to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static int write_data (flash_info_t * info, ulong dest, ulong * data) +{ + vu_long *addr = (vu_long *) dest; + ulong start; + int flag; + + /* Check if Flash is (sufficiently) erased */ + if (((addr[0] & data[0]) != data[0]) || + ((addr[1] & data[1]) != data[1])) { + return (2); + } + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts (); + + addr[0] = 0x00400040; /* write setup */ + write_via_fpu (addr, data); + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts (); + + start = get_timer (0); + + while (((addr[0] & 0x00800080) != 0x00800080) || + ((addr[1] & 0x00800080) != 0x00800080)) { + if (get_timer (start) > CFG_FLASH_WRITE_TOUT) { + addr[0] = 0x00FF00FF; /* restore read mode */ + return (1); + } + } + + addr[0] = 0x00FF00FF; /* restore read mode */ + + return (0); +} + +/*----------------------------------------------------------------------- + */ +static void write_via_fpu (vu_long * addr, ulong * data) +{ + __asm__ __volatile__ ("lfd 1, 0(%0)"::"r" (data)); + __asm__ __volatile__ ("stfd 1, 0(%0)"::"r" (addr)); +} + +/*----------------------------------------------------------------------- + */ +static __inline__ unsigned long get_msr (void) +{ + unsigned long msr; + + __asm__ __volatile__ ("mfmsr %0":"=r" (msr):); + + return msr; +} + +static __inline__ void set_msr (unsigned long msr) +{ + __asm__ __volatile__ ("mtmsr %0"::"r" (msr)); +} diff --git a/board/cpc45/pd67290.c b/board/cpc45/pd67290.c new file mode 100755 index 0000000..c84fbae --- /dev/null +++ b/board/cpc45/pd67290.c @@ -0,0 +1,68 @@ +/* pd67290.c - system configuration module for SPD67290 + * + * 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 + * + * (C) 2004 DENX Software Engineering, Heiko Schocher <hs@denx.de> + */ + +#include <common.h> +#include <malloc.h> +#include <net.h> +#include <asm/io.h> +#include <pci.h> + +/* imports */ +#include <mpc824x.h> + +static struct pci_device_id supported[] = { + {PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_6729}, + {} +}; + +/*************************************************************************** +* +* SPD67290Init - +* +* RETURNS: -1 on error, 0 if OK +*/ + +int SPD67290Init (void) +{ + pci_dev_t devno; + int idx = 0; /* general index */ + ulong membaseCsr; /* base address of device memory space */ + + /* find PD67290 device */ + if ((devno = pci_find_devices (supported, idx++)) < 0) { + printf ("No PD67290 device found !!\n"); + return -1; + } + /* - 0xfe000000 see MPC 8245 Users Manual Adress Map B */ + membaseCsr = PCMCIA_IO_BASE - 0xfe000000; + + /* set base address */ + pci_write_config_dword (devno, PCI_BASE_ADDRESS_0, membaseCsr); + + /* enable mapped memory and IO addresses */ + pci_write_config_dword (devno, + PCI_COMMAND, + PCI_COMMAND_MEMORY | + PCI_COMMAND_IO | PCI_COMMAND_WAIT); + return 0; +} diff --git a/board/cpc45/plx9030.c b/board/cpc45/plx9030.c new file mode 100755 index 0000000..99ec39a --- /dev/null +++ b/board/cpc45/plx9030.c @@ -0,0 +1,173 @@ +/* Plx9030.c - system configuration module for PLX9030 PCI to Local Bus Bridge */ +/* + * (C) Copyright 2002-2003 + * Josef Wagner, MicroSys GmbH, wagner@microsys.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * Date Modification by + * ------- ---------------------------------------------- --- + * 30sep02 converted from VxWorks to LINUX wa +*/ + + +/* +DESCRIPTION + +This is the configuration module for the PLX9030 PCI to Local Bus Bridge. +It configures the Chip select lines for SRAM (CS0), ST16C552 (CS1,CS2), Display and local +registers (CS3) on CPC45. +*/ + +/* includes */ + +#include <common.h> +#include <malloc.h> +#include <net.h> +#include <asm/io.h> +#include <pci.h> + +/* imports */ + + +/* defines */ +#define PLX9030_VENDOR_ID 0x10B5 +#define PLX9030_DEVICE_ID 0x9030 + +#undef PLX_DEBUG + +/* PLX9030 register offsets */ +#define P9030_LAS0RR 0x00 +#define P9030_LAS1RR 0x04 +#define P9030_LAS2RR 0x08 +#define P9030_LAS3RR 0x0c +#define P9030_EROMRR 0x10 +#define P9030_LAS0BA 0x14 +#define P9030_LAS1BA 0x18 +#define P9030_LAS2BA 0x1c +#define P9030_LAS3BA 0x20 +#define P9030_EROMBA 0x24 +#define P9030_LAS0BRD 0x28 +#define P9030_LAS1BRD 0x2c +#define P9030_LAS2BRD 0x30 +#define P9030_LAS3BRD 0x34 +#define P9030_EROMBRD 0x38 +#define P9030_CS0BASE 0x3C +#define P9030_CS1BASE 0x40 +#define P9030_CS2BASE 0x44 +#define P9030_CS3BASE 0x48 +#define P9030_INTCSR 0x4c +#define P9030_CNTRL 0x50 +#define P9030_GPIOC 0x54 + +/* typedefs */ + + +/* locals */ + +static struct pci_device_id supported[] = { + { PLX9030_VENDOR_ID, PLX9030_DEVICE_ID }, + { } +}; + +/* forward declarations */ +void sysOutLong(ulong address, ulong value); + + +/*************************************************************************** +* +* Plx9030Init - init CS0..CS3 for CPC45 +* +* +* RETURNS: N/A +*/ + +void Plx9030Init (void) +{ + pci_dev_t devno; + ulong membaseCsr; /* base address of device memory space */ + int idx = 0; /* general index */ + + + /* find plx9030 device */ + + if ((devno = pci_find_devices(supported, idx++)) < 0) + { + printf("No PLX9030 device found !!\n"); + return; + } + + +#ifdef PLX_DEBUG + printf("PLX 9030 device found ! devno = 0x%x\n",devno); +#endif + + membaseCsr = PCI_PLX9030_MEMADDR; + + /* set base address */ + pci_write_config_dword(devno, PCI_BASE_ADDRESS_0, membaseCsr); + + /* enable mapped memory and IO addresses */ + pci_write_config_dword(devno, + PCI_COMMAND, + PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER); + + + /* configure GBIOC */ + sysOutLong((membaseCsr + P9030_GPIOC), 0x00000FC0); /* CS2/CS3 enable */ + + /* configure CS0 (SRAM) */ + sysOutLong((membaseCsr + P9030_LAS0BA), 0x00000001); /* enable space base */ + sysOutLong((membaseCsr + P9030_LAS0RR), 0x0FE00000); /* 2 MByte */ + sysOutLong((membaseCsr + P9030_LAS0BRD), 0x51928900); /* 4 wait states */ + sysOutLong((membaseCsr + P9030_CS0BASE), 0x00100001); /* enable 2 MByte */ + /* remap CS0 (SRAM) */ + pci_write_config_dword(devno, PCI_BASE_ADDRESS_2, SRAM_BASE); + + /* configure CS1 (ST16552 / CHAN A) */ + sysOutLong((membaseCsr + P9030_LAS1BA), 0x00400001); /* enable space base */ + sysOutLong((membaseCsr + P9030_LAS1RR), 0x0FFFFF00); /* 256 byte */ + sysOutLong((membaseCsr + P9030_LAS1BRD), 0x55122900); /* 4 wait states */ + sysOutLong((membaseCsr + P9030_CS1BASE), 0x00400081); /* enable 256 Byte */ + /* remap CS1 (ST16552 / CHAN A) */ + /* remap CS1 (ST16552 / CHAN A) */ + pci_write_config_dword(devno, PCI_BASE_ADDRESS_3, ST16552_A_BASE); + + /* configure CS2 (ST16552 / CHAN B) */ + sysOutLong((membaseCsr + P9030_LAS2BA), 0x00800001); /* enable space base */ + sysOutLong((membaseCsr + P9030_LAS2RR), 0x0FFFFF00); /* 256 byte */ + sysOutLong((membaseCsr + P9030_LAS2BRD), 0x55122900); /* 4 wait states */ + sysOutLong((membaseCsr + P9030_CS2BASE), 0x00800081); /* enable 256 Byte */ + /* remap CS2 (ST16552 / CHAN B) */ + pci_write_config_dword(devno, PCI_BASE_ADDRESS_4, ST16552_B_BASE); + + /* configure CS3 (BCSR) */ + sysOutLong((membaseCsr + P9030_LAS3BA), 0x00C00001); /* enable space base */ + sysOutLong((membaseCsr + P9030_LAS3RR), 0x0FFFFF00); /* 256 byte */ + sysOutLong((membaseCsr + P9030_LAS3BRD), 0x55357A80); /* 9 wait states */ + sysOutLong((membaseCsr + P9030_CS3BASE), 0x00C00081); /* enable 256 Byte */ + /* remap CS3 (DISPLAY and BCSR) */ + pci_write_config_dword(devno, PCI_BASE_ADDRESS_5, BCSR_BASE); +} + +void sysOutLong(ulong address, ulong value) +{ + *(ulong*)address = cpu_to_le32(value); +} diff --git a/board/cpc45/u-boot.lds b/board/cpc45/u-boot.lds new file mode 100755 index 0000000..9ea26aa --- /dev/null +++ b/board/cpc45/u-boot.lds @@ -0,0 +1,136 @@ +/* + * (C) Copyright 2001-2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +OUTPUT_ARCH(powerpc) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); +/* Do we need any of these for elf? + __DYNAMIC = 0; */ +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/mpc824x/start.o (.text) + lib_ppc/board.o (.text) + lib_ppc/ppcstring.o (.text) + lib_generic/vsprintf.o (.text) + lib_generic/crc32.o (.text) + lib_generic/zlib.o (.text) + + . = DEFINED(env_offset) ? env_offset : .; + common/environment.o (.text) + + *(.text) + + *(.fixup) + *(.got1) + . = ALIGN(16); + *(.rodata) + *(.rodata1) + *(.rodata.str1.4) + *(.eh_frame) + } + .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 = .); +} |