From 0892b1930ee05e2600924f3a1910ea9c60b51d00 Mon Sep 17 00:00:00 2001 From: lefranc Date: Fri, 25 Jul 2008 13:10:22 +0000 Subject: - u-boot for arizona board git-svn-id: svn+ssh://pessac/svn/cesar/trunk@2663 017c9cb6-072f-447c-8318-d5b54f68fe89 --- cleopatre/u-boot-1.1.6/board/cpc45/Makefile | 44 ++ cleopatre/u-boot-1.1.6/board/cpc45/config.mk | 36 ++ cleopatre/u-boot-1.1.6/board/cpc45/cpc45.c | 275 +++++++++ cleopatre/u-boot-1.1.6/board/cpc45/flash.c | 522 ++++++++++++++++ cleopatre/u-boot-1.1.6/board/cpc45/pd67290.c | 818 ++++++++++++++++++++++++++ cleopatre/u-boot-1.1.6/board/cpc45/plx9030.c | 173 ++++++ cleopatre/u-boot-1.1.6/board/cpc45/u-boot.lds | 136 +++++ 7 files changed, 2004 insertions(+) create mode 100644 cleopatre/u-boot-1.1.6/board/cpc45/Makefile create mode 100644 cleopatre/u-boot-1.1.6/board/cpc45/config.mk create mode 100644 cleopatre/u-boot-1.1.6/board/cpc45/cpc45.c create mode 100644 cleopatre/u-boot-1.1.6/board/cpc45/flash.c create mode 100644 cleopatre/u-boot-1.1.6/board/cpc45/pd67290.c create mode 100644 cleopatre/u-boot-1.1.6/board/cpc45/plx9030.c create mode 100644 cleopatre/u-boot-1.1.6/board/cpc45/u-boot.lds (limited to 'cleopatre/u-boot-1.1.6/board/cpc45') diff --git a/cleopatre/u-boot-1.1.6/board/cpc45/Makefile b/cleopatre/u-boot-1.1.6/board/cpc45/Makefile new file mode 100644 index 0000000000..374fdd7650 --- /dev/null +++ b/cleopatre/u-boot-1.1.6/board/cpc45/Makefile @@ -0,0 +1,44 @@ +# +# (C) Copyright 2001-2006 +# 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 = $(obj)lib$(BOARD).a + +COBJS = $(BOARD).o flash.o plx9030.o pd67290.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/cleopatre/u-boot-1.1.6/board/cpc45/config.mk b/cleopatre/u-boot-1.1.6/board/cpc45/config.mk new file mode 100644 index 0000000000..bf9d9debc6 --- /dev/null +++ b/cleopatre/u-boot-1.1.6/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/cleopatre/u-boot-1.1.6/board/cpc45/cpc45.c b/cleopatre/u-boot-1.1.6/board/cpc45/cpc45.c new file mode 100644 index 0000000000..51b0085911 --- /dev/null +++ b/cleopatre/u-boot-1.1.6/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 +#include +#include +#include +#include +#include + +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/cleopatre/u-boot-1.1.6/board/cpc45/flash.c b/cleopatre/u-boot-1.1.6/board/cpc45/flash.c new file mode 100644 index 0000000000..37dd182ba4 --- /dev/null +++ b/cleopatre/u-boot-1.1.6/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 +#include +#include + +#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/cleopatre/u-boot-1.1.6/board/cpc45/pd67290.c b/cleopatre/u-boot-1.1.6/board/cpc45/pd67290.c new file mode 100644 index 0000000000..6ca3e7bd7a --- /dev/null +++ b/cleopatre/u-boot-1.1.6/board/cpc45/pd67290.c @@ -0,0 +1,818 @@ +/* + * (C) Copyright 2003-2005 + * 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 + * + ******************************************************************** + * + * Lots of code copied from: + * + * i82365.c 1.352 - Linux driver for Intel 82365 and compatible + * PC Card controllers, and Yenta-compatible PCI-to-CardBus controllers. + * (C) 1999 David A. Hinds + */ + +#include + +#ifdef CONFIG_I82365 + +#include +#include +#include +#include + +#include +#include +#include +#include + +static struct pci_device_id supported[] = { + {PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_6729}, + {0, 0} +}; + +#define CYCLE_TIME 120 + +#ifdef DEBUG +static void i82365_dump_regions (pci_dev_t dev); +#endif + +typedef struct socket_info_t { + pci_dev_t dev; + u_short bcr; + u_char pci_lat, cb_lat, sub_bus, cache; + u_int cb_phys; + + socket_cap_t cap; + u_short type; + u_int flags; + cirrus_state_t c_state; +} socket_info_t; + +/* These definitions must match the pcic table! */ +typedef enum pcic_id { + IS_PD6710, IS_PD672X, IS_VT83C469 +} pcic_id; + +typedef struct pcic_t { + char *name; +} pcic_t; + +static pcic_t pcic[] = { + {" Cirrus PD6710: "}, + {" Cirrus PD672x: "}, + {" VIA VT83C469: "}, +}; + +static socket_info_t socket; +static socket_state_t state; +static struct pccard_mem_map mem; +static struct pccard_io_map io; + +/*====================================================================*/ + +/* Some PCI shortcuts */ + +static int pci_readb (socket_info_t * s, int r, u_char * v) +{ + return pci_read_config_byte (s->dev, r, v); +} +static int pci_writeb (socket_info_t * s, int r, u_char v) +{ + return pci_write_config_byte (s->dev, r, v); +} +static int pci_readw (socket_info_t * s, int r, u_short * v) +{ + return pci_read_config_word (s->dev, r, v); +} +static int pci_writew (socket_info_t * s, int r, u_short v) +{ + return pci_write_config_word (s->dev, r, v); +} + +/*====================================================================*/ + +#define cb_readb(s) readb((s)->cb_phys + 1) +#define cb_writeb(s, v) writeb(v, (s)->cb_phys) +#define cb_writeb2(s, v) writeb(v, (s)->cb_phys + 1) +#define cb_readl(s, r) readl((s)->cb_phys + (r)) +#define cb_writel(s, r, v) writel(v, (s)->cb_phys + (r)) + + +static u_char i365_get (socket_info_t * s, u_short reg) +{ + u_char val; +#ifdef CONFIG_PCMCIA_SLOT_A + int slot = 0; +#else + int slot = 1; +#endif + + val = I365_REG (slot, reg); + + cb_writeb (s, val); + val = cb_readb (s); + + debug ("i365_get slot:%x reg: %x val: %x\n", slot, reg, val); + return val; +} + +static void i365_set (socket_info_t * s, u_short reg, u_char data) +{ +#ifdef CONFIG_PCMCIA_SLOT_A + int slot = 0; +#else + int slot = 1; +#endif + u_char val; + + val = I365_REG (slot, reg); + + cb_writeb (s, val); + cb_writeb2 (s, data); + + debug ("i365_set slot:%x reg: %x data:%x\n", slot, reg, data); +} + +static void i365_bset (socket_info_t * s, u_short reg, u_char mask) +{ + i365_set (s, reg, i365_get (s, reg) | mask); +} + +static void i365_bclr (socket_info_t * s, u_short reg, u_char mask) +{ + i365_set (s, reg, i365_get (s, reg) & ~mask); +} + +#if 0 /* not used */ +static void i365_bflip (socket_info_t * s, u_short reg, u_char mask, int b) +{ + u_char d = i365_get (s, reg); + + i365_set (s, reg, (b) ? (d | mask) : (d & ~mask)); +} + +static u_short i365_get_pair (socket_info_t * s, u_short reg) +{ + return (i365_get (s, reg) + (i365_get (s, reg + 1) << 8)); +} +#endif /* not used */ + +static void i365_set_pair (socket_info_t * s, u_short reg, u_short data) +{ + i365_set (s, reg, data & 0xff); + i365_set (s, reg + 1, data >> 8); +} + +/*====================================================================== + + Code to save and restore global state information for Cirrus + PD67xx controllers, and to set and report global configuration + options. + +======================================================================*/ + +#define flip(v,b,f) (v = ((f)<0) ? v : ((f) ? ((v)|(b)) : ((v)&(~b)))) + +static void cirrus_get_state (socket_info_t * s) +{ + int i; + cirrus_state_t *p = &s->c_state; + + p->misc1 = i365_get (s, PD67_MISC_CTL_1); + p->misc1 &= (PD67_MC1_MEDIA_ENA | PD67_MC1_INPACK_ENA); + p->misc2 = i365_get (s, PD67_MISC_CTL_2); + for (i = 0; i < 6; i++) + p->timer[i] = i365_get (s, PD67_TIME_SETUP (0) + i); + +} + +static void cirrus_set_state (socket_info_t * s) +{ + int i; + u_char misc; + cirrus_state_t *p = &s->c_state; + + misc = i365_get (s, PD67_MISC_CTL_2); + i365_set (s, PD67_MISC_CTL_2, p->misc2); + if (misc & PD67_MC2_SUSPEND) + udelay (50000); + misc = i365_get (s, PD67_MISC_CTL_1); + misc &= ~(PD67_MC1_MEDIA_ENA | PD67_MC1_INPACK_ENA); + i365_set (s, PD67_MISC_CTL_1, misc | p->misc1); + for (i = 0; i < 6; i++) + i365_set (s, PD67_TIME_SETUP (0) + i, p->timer[i]); +} + +static u_int cirrus_set_opts (socket_info_t * s) +{ + cirrus_state_t *p = &s->c_state; + u_int mask = 0xffff; +#if DEBUG + char buf[200]; + + memset (buf, 0, 200); +#endif + + if (has_ring == -1) + has_ring = 1; + flip (p->misc2, PD67_MC2_IRQ15_RI, has_ring); + flip (p->misc2, PD67_MC2_DYNAMIC_MODE, dynamic_mode); +#if DEBUG + if (p->misc2 & PD67_MC2_IRQ15_RI) + strcat (buf, " [ring]"); + if (p->misc2 & PD67_MC2_DYNAMIC_MODE) + strcat (buf, " [dyn mode]"); + if (p->misc1 & PD67_MC1_INPACK_ENA) + strcat (buf, " [inpack]"); +#endif + + if (p->misc2 & PD67_MC2_IRQ15_RI) + mask &= ~0x8000; + if (has_led > 0) { +#if DEBUG + strcat (buf, " [led]"); +#endif + mask &= ~0x1000; + } + if (has_dma > 0) { +#if DEBUG + strcat (buf, " [dma]"); +#endif + mask &= ~0x0600; + flip (p->misc2, PD67_MC2_FREQ_BYPASS, freq_bypass); +#if DEBUG + if (p->misc2 & PD67_MC2_FREQ_BYPASS) + strcat (buf, " [freq bypass]"); +#endif + } + + if (setup_time >= 0) + p->timer[0] = p->timer[3] = setup_time; + if (cmd_time > 0) { + p->timer[1] = cmd_time; + p->timer[4] = cmd_time * 2 + 4; + } + if (p->timer[1] == 0) { + p->timer[1] = 6; + p->timer[4] = 16; + if (p->timer[0] == 0) + p->timer[0] = p->timer[3] = 1; + } + if (recov_time >= 0) + p->timer[2] = p->timer[5] = recov_time; + + debug ("i82365 Opt: %s [%d/%d/%d] [%d/%d/%d]\n", + buf, + p->timer[0], p->timer[1], p->timer[2], + p->timer[3], p->timer[4], p->timer[5]); + + return mask; +} + +/*====================================================================== + + Routines to handle common CardBus options + +======================================================================*/ + +/* Default settings for PCI command configuration register */ +#define CMD_DFLT (PCI_COMMAND_IO|PCI_COMMAND_MEMORY| \ + PCI_COMMAND_MASTER|PCI_COMMAND_WAIT) + +static void cb_get_state (socket_info_t * s) +{ + pci_readb (s, PCI_CACHE_LINE_SIZE, &s->cache); + pci_readb (s, PCI_LATENCY_TIMER, &s->pci_lat); + pci_readb (s, CB_LATENCY_TIMER, &s->cb_lat); + pci_readb (s, CB_CARDBUS_BUS, &s->cap.cardbus); + pci_readb (s, CB_SUBORD_BUS, &s->sub_bus); + pci_readw (s, CB_BRIDGE_CONTROL, &s->bcr); +} + +static void cb_set_state (socket_info_t * s) +{ + pci_writew (s, PCI_COMMAND, CMD_DFLT); + pci_writeb (s, PCI_CACHE_LINE_SIZE, s->cache); + pci_writeb (s, PCI_LATENCY_TIMER, s->pci_lat); + pci_writeb (s, CB_LATENCY_TIMER, s->cb_lat); + pci_writeb (s, CB_CARDBUS_BUS, s->cap.cardbus); + pci_writeb (s, CB_SUBORD_BUS, s->sub_bus); + pci_writew (s, CB_BRIDGE_CONTROL, s->bcr); +} + +static void cb_set_opts (socket_info_t * s) +{ +} + +/*====================================================================== + + Power control for Cardbus controllers: used both for 16-bit and + Cardbus cards. + +======================================================================*/ + +static int cb_set_power (socket_info_t * s, socket_state_t * state) +{ + u_int reg = 0; + + reg = I365_PWR_NORESET; + if (state->flags & SS_PWR_AUTO) + reg |= I365_PWR_AUTO; + if (state->flags & SS_OUTPUT_ENA) + reg |= I365_PWR_OUT; + if (state->Vpp != 0) { + if (state->Vpp == 120) { + reg |= I365_VPP1_12V; + puts (" 12V card found: "); + } else if (state->Vpp == state->Vcc) { + reg |= I365_VPP1_5V; + } else { + puts (" power not found: "); + return -1; + } + } + if (state->Vcc != 0) { + reg |= I365_VCC_5V; + if (state->Vcc == 33) { + puts (" 3.3V card found: "); + i365_bset (s, PD67_MISC_CTL_1, PD67_MC1_VCC_3V); + } else if (state->Vcc == 50) { + puts (" 5V card found: "); + i365_bclr (s, PD67_MISC_CTL_1, PD67_MC1_VCC_3V); + } else { + puts (" power not found: "); + return -1; + } + } + + if (reg != i365_get (s, I365_POWER)) { + reg = (I365_PWR_OUT | I365_PWR_NORESET | I365_VCC_5V | I365_VPP1_5V); + i365_set (s, I365_POWER, reg); + } + + return 0; +} + +/*====================================================================== + + Generic routines to get and set controller options + +======================================================================*/ + +static void get_bridge_state (socket_info_t * s) +{ + cirrus_get_state (s); + cb_get_state (s); +} + +static void set_bridge_state (socket_info_t * s) +{ + cb_set_state (s); + i365_set (s, I365_GBLCTL, 0x00); + i365_set (s, I365_GENCTL, 0x00); + cirrus_set_state (s); +} + +static void set_bridge_opts (socket_info_t * s) +{ + cirrus_set_opts (s); + cb_set_opts (s); +} + +/*====================================================================*/ +#define PD67_EXT_INDEX 0x2e /* Extension index */ +#define PD67_EXT_DATA 0x2f /* Extension data */ +#define PD67_EXD_VS1(s) (0x01 << ((s)<<1)) + +#define pd67_ext_get(s, r) \ + (i365_set(s, PD67_EXT_INDEX, r), i365_get(s, PD67_EXT_DATA)) + +static int i365_get_status (socket_info_t * s, u_int * value) +{ + u_int status; + u_char val; + u_char power, vcc, vpp; + u_int powerstate; + + status = i365_get (s, I365_IDENT); + status = i365_get (s, I365_STATUS); + *value = ((status & I365_CS_DETECT) == I365_CS_DETECT) ? SS_DETECT : 0; + if (i365_get (s, I365_INTCTL) & I365_PC_IOCARD) { + *value |= (status & I365_CS_STSCHG) ? 0 : SS_STSCHG; + } else { + *value |= (status & I365_CS_BVD1) ? 0 : SS_BATDEAD; + *value |= (status & I365_CS_BVD2) ? 0 : SS_BATWARN; + } + *value |= (status & I365_CS_WRPROT) ? SS_WRPROT : 0; + *value |= (status & I365_CS_READY) ? SS_READY : 0; + *value |= (status & I365_CS_POWERON) ? SS_POWERON : 0; + + /* Check for Cirrus CL-PD67xx chips */ + i365_set (s, PD67_CHIP_INFO, 0); + val = i365_get (s, PD67_CHIP_INFO); + s->type = -1; + if ((val & PD67_INFO_CHIP_ID) == PD67_INFO_CHIP_ID) { + val = i365_get (s, PD67_CHIP_INFO); + if ((val & PD67_INFO_CHIP_ID) == 0) { + s->type = (val & PD67_INFO_SLOTS) ? IS_PD672X : IS_PD6710; + i365_set (s, PD67_EXT_INDEX, 0xe5); + if (i365_get (s, PD67_EXT_INDEX) != 0xe5) + s->type = IS_VT83C469; + } + } else { + printf ("no Cirrus Chip found\n"); + *value = 0; + return -1; + } + + power = i365_get (s, I365_POWER); + state.flags |= (power & I365_PWR_AUTO) ? SS_PWR_AUTO : 0; + state.flags |= (power & I365_PWR_OUT) ? SS_OUTPUT_ENA : 0; + vcc = power & I365_VCC_MASK; + vpp = power & I365_VPP1_MASK; + state.Vcc = state.Vpp = 0; + if((vcc== 0) || (vpp == 0)) { + /* + * On the Cirrus we get the info which card voltage + * we have in EXTERN DATA and write it to MISC_CTL1 + */ + powerstate = pd67_ext_get(s, PD67_EXTERN_DATA); + if (powerstate & PD67_EXD_VS1(0)) { + /* 5V Card */ + i365_bclr (s, PD67_MISC_CTL_1, PD67_MC1_VCC_3V); + } else { + /* 3.3V Card */ + i365_bset (s, PD67_MISC_CTL_1, PD67_MC1_VCC_3V); + } + i365_set (s, I365_POWER, (I365_PWR_OUT | I365_PWR_NORESET | I365_VCC_5V | I365_VPP1_5V)); + power = i365_get (s, I365_POWER); + } + if (power & I365_VCC_5V) { + state.Vcc = (i365_get(s, PD67_MISC_CTL_1) & PD67_MC1_VCC_3V) ? 33 : 50; + } + + if (power == I365_VPP1_12V) + state.Vpp = 120; + + /* IO card, RESET flags, IO interrupt */ + power = i365_get (s, I365_INTCTL); + state.flags |= (power & I365_PC_RESET) ? 0 : SS_RESET; + if (power & I365_PC_IOCARD) + state.flags |= SS_IOCARD; + state.io_irq = power & I365_IRQ_MASK; + + /* Card status change mask */ + power = i365_get (s, I365_CSCINT); + state.csc_mask = (power & I365_CSC_DETECT) ? SS_DETECT : 0; + if (state.flags & SS_IOCARD) + state.csc_mask |= (power & I365_CSC_STSCHG) ? SS_STSCHG : 0; + else { + state.csc_mask |= (power & I365_CSC_BVD1) ? SS_BATDEAD : 0; + state.csc_mask |= (power & I365_CSC_BVD2) ? SS_BATWARN : 0; + state.csc_mask |= (power & I365_CSC_READY) ? SS_READY : 0; + } + debug ("i82365: GetStatus(0) = flags %#3.3x, Vcc %d, Vpp %d, " + "io_irq %d, csc_mask %#2.2x\n", state.flags, + state.Vcc, state.Vpp, state.io_irq, state.csc_mask); + + return 0; +} /* i365_get_status */ + +static int i365_set_socket (socket_info_t * s, socket_state_t * state) +{ + u_char reg; + + set_bridge_state (s); + + /* IO card, RESET flag */ + reg = 0; + reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET; + reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0; + i365_set (s, I365_INTCTL, reg); + + cb_set_power (s, state); + +#if 0 + /* Card status change interrupt mask */ + reg = s->cs_irq << 4; + if (state->csc_mask & SS_DETECT) + reg |= I365_CSC_DETECT; + if (state->flags & SS_IOCARD) { + if (state->csc_mask & SS_STSCHG) + reg |= I365_CSC_STSCHG; + } else { + if (state->csc_mask & SS_BATDEAD) + reg |= I365_CSC_BVD1; + if (state->csc_mask & SS_BATWARN) + reg |= I365_CSC_BVD2; + if (state->csc_mask & SS_READY) + reg |= I365_CSC_READY; + } + i365_set (s, I365_CSCINT, reg); + i365_get (s, I365_CSC); +#endif /* 0 */ + + return 0; +} /* i365_set_socket */ + +/*====================================================================*/ + +static int i365_set_mem_map (socket_info_t * s, struct pccard_mem_map *mem) +{ + u_short base, i; + u_char map; + + debug ("i82365: SetMemMap(%d, %#2.2x, %d ns, %#5.5lx-%#5.5lx, %#5.5x)\n", + mem->map, mem->flags, mem->speed, + mem->sys_start, mem->sys_stop, mem->card_start); + + map = mem->map; + if ((map > 4) || + (mem->card_start > 0x3ffffff) || + (mem->sys_start > mem->sys_stop) || + (mem->speed > 1000)) { + return -1; + } + + /* Turn off the window before changing anything */ + if (i365_get (s, I365_ADDRWIN) & I365_ENA_MEM (map)) + i365_bclr (s, I365_ADDRWIN, I365_ENA_MEM (map)); + + /* Take care of high byte, for PCI controllers */ + i365_set (s, CB_MEM_PAGE (map), mem->sys_start >> 24); + + base = I365_MEM (map); + i = (mem->sys_start >> 12) & 0x0fff; + if (mem->flags & MAP_16BIT) + i |= I365_MEM_16BIT; + if (mem->flags & MAP_0WS) + i |= I365_MEM_0WS; + i365_set_pair (s, base + I365_W_START, i); + + i = (mem->sys_stop >> 12) & 0x0fff; + switch (mem->speed / CYCLE_TIME) { + case 0: + break; + case 1: + i |= I365_MEM_WS0; + break; + case 2: + i |= I365_MEM_WS1; + break; + default: + i |= I365_MEM_WS1 | I365_MEM_WS0; + break; + } + i365_set_pair (s, base + I365_W_STOP, i); + + i = 0; + if (mem->flags & MAP_WRPROT) + i |= I365_MEM_WRPROT; + if (mem->flags & MAP_ATTRIB) + i |= I365_MEM_REG; + i365_set_pair (s, base + I365_W_OFF, i); + + /* set System Memory map Upper Adress */ + i365_set(s, PD67_EXT_INDEX, PD67_MEM_PAGE(map)); + i365_set(s, PD67_EXT_DATA, ((mem->sys_start >> 24) & 0xff)); + + /* Turn on the window if necessary */ + if (mem->flags & MAP_ACTIVE) + i365_bset (s, I365_ADDRWIN, I365_ENA_MEM (map)); + return 0; +} /* i365_set_mem_map */ + +static int i365_set_io_map (socket_info_t * s, struct pccard_io_map *io) +{ + u_char map, ioctl; + + map = io->map; + /* comment out: comparison is always false due to limited range of data type */ + if ((map > 1) || /* (io->start > 0xffff) || (io->stop > 0xffff) || */ + (io->stop < io->start)) + return -1; + /* Turn off the window before changing anything */ + if (i365_get (s, I365_ADDRWIN) & I365_ENA_IO (map)) + i365_bclr (s, I365_ADDRWIN, I365_ENA_IO (map)); + i365_set_pair (s, I365_IO (map) + I365_W_START, io->start); + i365_set_pair (s, I365_IO (map) + I365_W_STOP, io->stop); + ioctl = i365_get (s, I365_IOCTL) & ~I365_IOCTL_MASK (map); + if (io->speed) + ioctl |= I365_IOCTL_WAIT (map); + if (io->flags & MAP_0WS) + ioctl |= I365_IOCTL_0WS (map); + if (io->flags & MAP_16BIT) + ioctl |= I365_IOCTL_16BIT (map); + if (io->flags & MAP_AUTOSZ) + ioctl |= I365_IOCTL_IOCS16 (map); + i365_set (s, I365_IOCTL, ioctl); + /* Turn on the window if necessary */ + if (io->flags & MAP_ACTIVE) + i365_bset (s, I365_ADDRWIN, I365_ENA_IO (map)); + return 0; +} /* i365_set_io_map */ + +/*====================================================================*/ + +/* + * PCI_ADDR = (HOST_ADDR - 0xfe000000) + * see MPC 8245 Users Manual Adress Map B + */ +#define HOST_TO_PCI(addr) ((addr) - 0xfe000000) +#define PCI_TO_HOST(addr) ((addr) + 0xfe000000) + +int i82365_init (void) +{ + u_int val; + int i; + + if ((socket.dev = pci_find_devices (supported, 0)) < 0) { + /* Controller not found */ + printf ("No PD67290 device found !!\n"); + return 1; + } + debug ("i82365 Device Found!\n"); + + socket.cb_phys = PCMCIA_IO_BASE; + + /* set base address */ + pci_write_config_dword (socket.dev, PCI_BASE_ADDRESS_0, + HOST_TO_PCI(socket.cb_phys)); + + /* enable mapped memory and IO addresses */ + pci_write_config_dword (socket.dev, + PCI_COMMAND, + PCI_COMMAND_MEMORY | + PCI_COMMAND_IO | PCI_COMMAND_WAIT); + + get_bridge_state (&socket); + set_bridge_opts (&socket); + + i = i365_get_status (&socket, &val); + + if (i > -1) { + puts (pcic[socket.type].name); + } else { + printf ("i82365: Controller not found.\n"); + return 1; + } + if((val & SS_DETECT) != SS_DETECT){ + puts ("No card\n"); + return 1; + } + + state.flags |= SS_OUTPUT_ENA; + + i365_set_socket (&socket, &state); + + for (i = 500; i; i--) { + if ((i365_get (&socket, I365_STATUS) & I365_CS_READY)) + break; + udelay (1000); + } + + if (i == 0) { + /* PC Card not ready for data transfer */ + puts ("i82365 PC Card not ready for data transfer\n"); + return 1; + } + debug (" PC Card ready for data transfer: "); + + mem.map = 0; + mem.flags = MAP_ATTRIB | MAP_ACTIVE; + mem.speed = 300; + mem.sys_start = CFG_PCMCIA_MEM_ADDR; + mem.sys_stop = CFG_PCMCIA_MEM_ADDR + CFG_PCMCIA_MEM_SIZE - 1; + mem.card_start = 0; + i365_set_mem_map (&socket, &mem); + + mem.map = 1; + mem.flags = MAP_ACTIVE; + mem.speed = 300; + mem.sys_start = CFG_PCMCIA_MEM_ADDR + CFG_PCMCIA_MEM_SIZE; + mem.sys_stop = CFG_PCMCIA_MEM_ADDR + (2 * CFG_PCMCIA_MEM_SIZE) - 1; + mem.card_start = 0; + i365_set_mem_map (&socket, &mem); + +#ifdef DEBUG + i82365_dump_regions (socket.dev); +#endif + + return 0; +} + +void i82365_exit (void) +{ + io.map = 0; + io.flags = 0; + io.speed = 0; + io.start = 0; + io.stop = 0x1; + + i365_set_io_map (&socket, &io); + + mem.map = 0; + mem.flags = 0; + mem.speed = 0; + mem.sys_start = 0; + mem.sys_stop = 0x1000; + mem.card_start = 0; + + i365_set_mem_map (&socket, &mem); + + mem.map = 1; + mem.flags = 0; + mem.speed = 0; + mem.sys_start = 0; + mem.sys_stop = 0x1000; + mem.card_start = 0; + + i365_set_mem_map (&socket, &mem); + + state.Vcc = state.Vpp = 0; + + i365_set_socket (&socket, &state); +} + +int pcmcia_on (void) +{ + u_int rc; + + debug ("Enable PCMCIA " PCMCIA_SLOT_MSG "\n"); + + rc = i82365_init(); + if (rc) + goto exit; + + rc = check_ide_device(0); + if (rc == 0) + goto exit; + + i82365_exit(); + +exit: + return rc; +} + +#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA) +int pcmcia_off (void) +{ + printf ("Disable PCMCIA " PCMCIA_SLOT_MSG "\n"); + + i82365_exit(); + + return 0; +} +#endif + +/*====================================================================== + + Debug stuff + +======================================================================*/ + +#ifdef DEBUG +static void i82365_dump_regions (pci_dev_t dev) +{ + u_int tmp[2]; + u_int *mem = (void *) socket.cb_phys; + u_char *cis = (void *) CFG_PCMCIA_MEM_ADDR; + u_char *ide = (void *) (CFG_ATA_BASE_ADDR + CFG_ATA_REG_OFFSET); + + pci_read_config_dword (dev, 0x00, tmp + 0); + pci_read_config_dword (dev, 0x80, tmp + 1); + + printf ("PCI CONF: %08X ... %08X\n", + tmp[0], tmp[1]); + printf ("PCI MEM: ... %08X ... %08X\n", + mem[0x8 / 4], mem[0x800 / 4]); + printf ("CIS: ...%c%c%c%c%c%c%c%c...\n", + cis[0x38], cis[0x3a], cis[0x3c], cis[0x3e], + cis[0x40], cis[0x42], cis[0x44], cis[0x48]); + printf ("CIS CONF: %02X %02X %02X ...\n", + cis[0x200], cis[0x202], cis[0x204]); + printf ("IDE: %02X %02X %02X %02X %02X %02X %02X %02X\n", + ide[0], ide[1], ide[2], ide[3], + ide[4], ide[5], ide[6], ide[7]); +} +#endif /* DEBUG */ + +#endif /* CONFIG_I82365 */ diff --git a/cleopatre/u-boot-1.1.6/board/cpc45/plx9030.c b/cleopatre/u-boot-1.1.6/board/cpc45/plx9030.c new file mode 100644 index 0000000000..99ec39af7a --- /dev/null +++ b/cleopatre/u-boot-1.1.6/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 +#include +#include +#include +#include + +/* 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/cleopatre/u-boot-1.1.6/board/cpc45/u-boot.lds b/cleopatre/u-boot-1.1.6/board/cpc45/u-boot.lds new file mode 100644 index 0000000000..9ea26aa265 --- /dev/null +++ b/cleopatre/u-boot-1.1.6/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 = .); +} -- cgit v1.2.3