diff options
| -rw-r--r-- | board/eltec/bab7xx/Makefile | 57 | ||||
| -rw-r--r-- | board/eltec/bab7xx/config.mk | 26 | ||||
| -rw-r--r-- | board/eltec/bab7xx/dc_srom.c | 291 | ||||
| -rw-r--r-- | board/eltec/bab7xx/flash.c | 513 | ||||
| -rw-r--r-- | board/eltec/bab7xx/l2cache.c | 159 | ||||
| -rw-r--r-- | board/eltec/bab7xx/misc.c | 547 | ||||
| -rw-r--r-- | board/eltec/bab7xx/pci.c | 120 | ||||
| -rw-r--r-- | board/eltec/bab7xx/srom.h | 102 | ||||
| -rw-r--r-- | board/eltec/elppc/Makefile | 57 | ||||
| -rw-r--r-- | board/eltec/elppc/config.mk | 26 | ||||
| -rw-r--r-- | board/eltec/elppc/flash.c | 513 | ||||
| -rw-r--r-- | board/eltec/elppc/misc.c | 258 | ||||
| -rw-r--r-- | board/eltec/elppc/mpc107_i2c.c | 320 | ||||
| -rw-r--r-- | board/eltec/elppc/pci.c | 97 | ||||
| -rw-r--r-- | board/eltec/elppc/srom.h | 102 | 
15 files changed, 3188 insertions, 0 deletions
| diff --git a/board/eltec/bab7xx/Makefile b/board/eltec/bab7xx/Makefile new file mode 100644 index 000000000..6e412c2e0 --- /dev/null +++ b/board/eltec/bab7xx/Makefile @@ -0,0 +1,57 @@ +# +# (C) Copyright 2000 +# 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 pci.o misc.o el_srom.o dc_srom.o l2cache.o + +SOBJS	= asm_init.o + +$(LIB):	.depend $(OBJS) $(SOBJS) +	$(AR) crv $@ $^ + +clean: +	rm -f $(SOBJS) $(OBJS) + +distclean:	clean +	rm -f $(LIB) core *.bak .depend + +######################################################################### + +.depend:	Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) +		$(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### + + + + + + + + + diff --git a/board/eltec/bab7xx/config.mk b/board/eltec/bab7xx/config.mk new file mode 100644 index 000000000..aa463c5dc --- /dev/null +++ b/board/eltec/bab7xx/config.mk @@ -0,0 +1,26 @@ +# +# (C) Copyright 2000 +# 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 +# + +TEXT_BASE = 0xFFF00000 + +PLATFORM_CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE) diff --git a/board/eltec/bab7xx/dc_srom.c b/board/eltec/bab7xx/dc_srom.c new file mode 100644 index 000000000..ef956e6e9 --- /dev/null +++ b/board/eltec/bab7xx/dc_srom.c @@ -0,0 +1,291 @@ +/* + * (C) Copyright 2002 ELTEC Elektronik AG + * Frank Gottschling <fgottschling@eltec.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 + */ + +/* + * SRom I/O routines. + */ + +#include <common.h> +#include <pci.h> +#include "srom.h" + +#define SROM_RD         0x00004000    /* Read from Boot ROM */ +#define SROM_WR         0x00002000    /* Write to Boot ROM */ +#define SROM_SR         0x00000800    /* Select Serial ROM when set */ + +#define DT_IN           0x00000004    /* Serial Data In */ +#define DT_CLK          0x00000002    /* Serial ROM Clock */ +#define DT_CS           0x00000001    /* Serial ROM Chip Select */ + +static u_int         dc_srom_iobase; + +/*----------------------------------------------------------------------------*/ + +static int inl(u_long addr) +{ +    return le32_to_cpu(*(volatile u_long *)(addr)); +} + +/*----------------------------------------------------------------------------*/ + +static void outl (int command, u_long addr) +{ +    *(volatile u_long *)(addr) = cpu_to_le32(command); +} + +/*----------------------------------------------------------------------------*/ + +static void sendto_srom(u_int command, u_long addr) +{ +    outl(command, addr); +    udelay(1); + +    return; +} + +/*----------------------------------------------------------------------------*/ + +static int getfrom_srom(u_long addr) +{ +    s32 tmp; + +    tmp = inl(addr); +    udelay(1); + +    return tmp; +} + +/*----------------------------------------------------------------------------*/ + +static void srom_latch (u_int command, u_long addr) +{ +    sendto_srom (command, addr); +    sendto_srom (command | DT_CLK, addr); +    sendto_srom (command, addr); + +    return; +} + +/*----------------------------------------------------------------------------*/ + +static void srom_command_rd (u_int command, u_long addr) +{ +    srom_latch (command, addr); +    srom_latch (command, addr); +    srom_latch ((command & 0x0000ff00) | DT_CS, addr); + +    return; +} + +/*----------------------------------------------------------------------------*/ + +static void srom_command_wr (u_int command, u_long addr) +{ +    srom_latch (command, addr); +    srom_latch ((command & 0x0000ff00) | DT_CS, addr); +    srom_latch (command, addr); + +    return; +} + +/*----------------------------------------------------------------------------*/ + +static void srom_address(u_int command, u_long addr, u_char offset) +{ +    int i; +    signed char a; + +    a = (char)(offset << 2); +    for (i=0; i<6; i++, a <<= 1) +    { +        srom_latch(command | ((a < 0) ? DT_IN : 0), addr); +    } +    udelay(1); + +    i = (getfrom_srom(addr) >> 3) & 0x01; + +    return; +} +/*----------------------------------------------------------------------------*/ + +static short srom_data_rd (u_int command, u_long addr) +{ +    int i; +    short word = 0; +    s32 tmp; + +    for (i=0; i<16; i++) +    { +        sendto_srom(command  | DT_CLK, addr); +        tmp = getfrom_srom(addr); +        sendto_srom(command, addr); + +        word = (word << 1) | ((tmp >> 3) & 0x01); +    } + +    sendto_srom(command & 0x0000ff00, addr); + +    return word; +} + +/*----------------------------------------------------------------------------*/ + +static int srom_data_wr (u_int command, u_long addr, short val) +{ +    int i; +    u_long longVal; +    s32 tmp; + +    longVal = (u_long)(le16_to_cpu(val)); + +    for (i=0; i<16; i++) +    { +        tmp = (longVal & 0x8000)>>13; + +        sendto_srom (tmp | command, addr); +        sendto_srom (tmp | command  | DT_CLK, addr); +        sendto_srom (tmp | command, addr); + +        longVal = longVal<<1; +    } + +    sendto_srom(command & 0x0000ff00, addr); +    sendto_srom(command, addr); + +    tmp = 100; +    do +    { +        if ((getfrom_srom(dc_srom_iobase) & 0x8) == 0x8) +            break; +        udelay(1000); +    } while (--tmp); + +    if (tmp == 0) +    { +        printf("Write DEC21143 SRom timed out !\n"); +        return (-1); +    } + +    return 0; +} + + +/*----------------------------------------------------------------------------*/ +static short srom_rd (u_long addr, u_char offset) +{ +    sendto_srom (SROM_RD | SROM_SR, addr); +    srom_latch (SROM_RD | SROM_SR | DT_CS, addr); + +    srom_command_rd (SROM_RD | SROM_SR | DT_IN | DT_CS, addr); + +    srom_address (SROM_RD | SROM_SR | DT_CS, addr, offset); + +    return srom_data_rd (SROM_RD | SROM_SR | DT_CS, addr); +} + +/*----------------------------------------------------------------------------*/ + +static void srom_wr_enable (u_long addr) +{ +    int i; + +    sendto_srom (SROM_WR | SROM_SR, addr); +    srom_latch (SROM_WR | SROM_SR | DT_CS, addr); + +    srom_latch (SROM_WR | SROM_SR | DT_IN | DT_CS, addr); +    srom_latch (SROM_WR | SROM_SR | DT_CS, addr); +    srom_latch (SROM_WR | SROM_SR | DT_CS, addr); + +    for (i=0; i<6; i++) +    { +        srom_latch (SROM_WR | SROM_SR | DT_IN | DT_CS, addr); +    } +} + +/*----------------------------------------------------------------------------*/ + +static int srom_wr (u_long addr, u_char offset, short val) +{ +    srom_wr_enable (addr); + +    sendto_srom (SROM_WR | SROM_SR, addr); +    srom_latch (SROM_WR | SROM_SR | DT_CS, addr); + +    srom_command_wr (SROM_WR | SROM_SR | DT_IN | DT_CS, addr); + +    srom_address (SROM_WR | SROM_SR | DT_CS, addr, offset); + +    return srom_data_wr (SROM_WR | SROM_SR | DT_CS, addr, val); +} + +/*----------------------------------------------------------------------------*/ +/* + * load data from the srom + */ +int dc_srom_load (u_short *dest) +{ +    int offset; +    short tmp; + +    /* get srom iobase from local network controller */ +    pci_read_config_dword(PCI_BDF(0,14,0), PCI_BASE_ADDRESS_1, &dc_srom_iobase); +    dc_srom_iobase &= PCI_BASE_ADDRESS_MEM_MASK; +    dc_srom_iobase  = pci_mem_to_phys(PCI_BDF(0,14,0), dc_srom_iobase); +    dc_srom_iobase += 0x48;            /* io offset for srom access */ + +    memset (dest, 0, 128); +    for (offset=0; offset<64; offset++) +    { +        tmp = srom_rd (dc_srom_iobase, offset); +        *dest++ = le16_to_cpu(tmp); +    } + +    return (0); +} + +/*----------------------------------------------------------------------------*/ + +/* + * store data into the srom + */ +int dc_srom_store (u_short *src) +{ +    int offset; + +    /* get srom iobase from local network controller */ +    pci_read_config_dword(PCI_BDF(0,14,0), PCI_BASE_ADDRESS_1, &dc_srom_iobase); +    dc_srom_iobase &= PCI_BASE_ADDRESS_MEM_MASK; +    dc_srom_iobase  = pci_mem_to_phys(PCI_BDF(0,14,0), dc_srom_iobase); +    dc_srom_iobase += 0x48;            /* io offset for srom access */ + +    for (offset=0; offset<64; offset++) +    { +        if (srom_wr (dc_srom_iobase, offset, *src) == -1) +                return (-1); +        src++; +    } + +    return (0); +} + +/*----------------------------------------------------------------------------*/ diff --git a/board/eltec/bab7xx/flash.c b/board/eltec/bab7xx/flash.c new file mode 100644 index 000000000..5834c9999 --- /dev/null +++ b/board/eltec/bab7xx/flash.c @@ -0,0 +1,513 @@ +/* + * (C) Copyright 2000 + * 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 + */ + +/* + * 07-10-2002 Frank Gottschling: added 29F032 flash (ELPPC). + *        fixed monitor protection part + * + * 09-18-2001 Andreas Heppel: Reduced the code in here to the usage + *        of AMD's 29F040 and 29F016 flashes, since the BAB7xx does use + *        any other. + */ + +#include <common.h> +#include <asm/processor.h> +#include <asm/pci_io.h> + +flash_info_t    flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ + +ulong flash_get_size (vu_long *addr, flash_info_t *info); +static int write_word (flash_info_t *info, ulong dest, ulong data); + +/*flash command address offsets*/ + +#define ADDR0           (0x555) +#define ADDR1           (0x2AA) +#define ADDR3           (0x001) + +#define FLASH_WORD_SIZE unsigned char + +/*----------------------------------------------------------------------------*/ + +unsigned long flash_init (void) +{ +    unsigned long size1, size2; +    int i; + +    /* Init: no FLASHes known */ +    for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) +    { +        flash_info[i].flash_id = FLASH_UNKNOWN; +    } + +    /* initialise 1st flash */ +    size1 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]); + +    if (flash_info[0].flash_id == FLASH_UNKNOWN) +    { +        printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n", +            size1, size1<<20); +    } + +    /* initialise 2nd flash */ +    size2 = flash_get_size((vu_long *)FLASH_BASE1_PRELIM, &flash_info[1]); + +    if (flash_info[1].flash_id == FLASH_UNKNOWN) +    { +        printf ("## Unknown FLASH on Bank 1 - Size = 0x%08lx = %ld MB\n", +            size2, size2<<20); +    } + +    /* monitor protection ON by default */ +    if (size1 == 512*1024) +    { +        (void)flash_protect(FLAG_PROTECT_SET, +                FLASH_BASE0_PRELIM, +                FLASH_BASE0_PRELIM+CFG_MONITOR_LEN-1, +                &flash_info[0]); +    } +    if (size2 == 512*1024) +    { +        (void)flash_protect(FLAG_PROTECT_SET, +                FLASH_BASE1_PRELIM, +                FLASH_BASE1_PRELIM+CFG_MONITOR_LEN-1, +                &flash_info[1]); +    } +    if (size2 == 4*1024*1024) +    { +        (void)flash_protect(FLAG_PROTECT_SET, +                CFG_FLASH_BASE, +                CFG_FLASH_BASE+CFG_MONITOR_LEN-1, +                &flash_info[1]); +    } + +    return (size1 + size2); +} + +/*----------------------------------------------------------------------------*/ + +void flash_print_info  (flash_info_t *info) +{ +    int i; +    int k; +    int size; +    int erased; +    volatile unsigned long *flash; + +    if (info->flash_id == FLASH_UNKNOWN) { +        printf ("missing or unknown FLASH type\n"); +        flash_init(); +    } + +    if (info->flash_id == FLASH_UNKNOWN) { +        printf ("missing or unknown FLASH type\n"); +        return; +    } + +    switch (info->flash_id & FLASH_VENDMASK) { +    case FLASH_MAN_AMD: +        printf ("AMD "); +        break; +    default: +        printf ("Unknown Vendor "); +        break; +    } + +    switch (info->flash_id & FLASH_TYPEMASK) { +    case AMD_ID_F040B: +        printf ("AM29F040B (4 Mbit)\n"); +        break; +    case AMD_ID_F016D: +        printf ("AM29F016D (16 Mbit)\n"); +        break; +    case AMD_ID_F032B: +        printf ("AM29F032B (32 Mbit)\n"); +        break; +   default: +        printf ("Unknown Chip Type\n"); +        break; +    } + +    if (info->size >= (1 << 20)) { +        printf ("  Size: %ld MB in %d Sectors\n", info->size >> 20, info->sector_count); +    } else { +        printf ("  Size: %ld kB in %d Sectors\n", info->size >> 10, info->sector_count); +    } + +    printf ("  Sector Start Addresses:"); +    for (i=0; i<info->sector_count; ++i) { +        /* +        * Check if whole sector is erased +        */ +        if (i != (info->sector_count-1)) +            size = info->start[i+1] - info->start[i]; +        else +            size = info->start[0] + info->size - info->start[i]; + +        erased = 1; +        flash = (volatile unsigned long *)info->start[i]; +        size = size >> 2;        /* divide by 4 for longword access */ +        for (k=0; k<size; k++) { +            if (*flash++ != 0xffffffff) { +                erased = 0; +                break; +            } +        } + +        if ((i % 5) == 0) +            printf ("\n   "); + +        printf (" %08lX%s%s", +            info->start[i], +            erased ? " E" : "  ", +            info->protect[i] ? "RO " : "   "); +    } +    printf ("\n"); +} + +/*----------------------------------------------------------------------------*/ +/* + * The following code cannot be run from FLASH! + */ +ulong flash_get_size (vu_long *addr, flash_info_t *info) +{ +    short i; +    ulong vendor, devid; +    ulong base = (ulong)addr; +    volatile unsigned char *caddr = (unsigned char *)addr; + +#ifdef DEBUG +    printf("flash_get_size for address 0x%lx: \n", (unsigned long)caddr); +#endif + +    /* Write auto select command: read Manufacturer ID */ +    caddr[0] = 0xF0;   /* reset bank */ +    udelay(10); + +    eieio(); +    caddr[0x555] = 0xAA; +    udelay(10); +    caddr[0x2AA] = 0x55; +    udelay(10); +    caddr[0x555] = 0x90; + +    udelay(10); + +    vendor = caddr[0]; +    devid = caddr[1]; + +#ifdef DEBUG +    printf("Manufacturer: 0x%lx\n", vendor); +#endif + +    vendor &= 0xff; +    devid &= 0xff; + +    /* We accept only two AMD types */ +    switch (vendor) { +    case (FLASH_WORD_SIZE)AMD_MANUFACT: +        info->flash_id = FLASH_MAN_AMD; +        break; +    default: +        info->flash_id = FLASH_UNKNOWN; +        info->sector_count = 0; +        info->size = 0; +        return (0);         /* no or unknown flash  */ +    } + +    switch (devid) { +    case (FLASH_WORD_SIZE)AMD_ID_F040B: +        info->flash_id |= AMD_ID_F040B; +        info->sector_count = 8; +        info->size = 0x00080000; +        break;              /* => 0.5 MB      */ + +    case (FLASH_WORD_SIZE)AMD_ID_F016D: +        info->flash_id |= AMD_ID_F016D; +        info->sector_count = 32; +        info->size         = 0x00200000; +        break;              /* => 2 MB      */ + +    case (FLASH_WORD_SIZE)AMD_ID_F032B: +        info->flash_id |= AMD_ID_F032B; +        info->sector_count = 64; +        info->size         = 0x00400000; +        break;              /* => 4 MB      */ + +    default: +        info->flash_id = FLASH_UNKNOWN; +        return (0);         /* => no or unknown flash */ + +    } + +#ifdef DEBUG +    printf("flash id 0x%lx; sector count 0x%x, size 0x%lx\n", info->flash_id, info->sector_count, info->size); +#endif + +    /* check for protected sectors */ +    for (i = 0; i < info->sector_count; i++) { +        /* sector base address */ +        info->start[i] = base + i * (info->size / info->sector_count); +        /* read sector protection at sector address, (A7 .. A0) = 0x02 */ +        /* D0 = 1 if protected */ +        caddr = (volatile unsigned char *)(info->start[i]); +        info->protect[i] = caddr[2] & 1; +    } + +    /* +     * Prevent writes to uninitialized FLASH. +     */ +    if (info->flash_id != FLASH_UNKNOWN) { +        caddr = (volatile unsigned char *)info->start[0]; +        caddr[0] = 0xF0;   /* reset bank */ +    } + +    return (info->size); +} + +/*----------------------------------------------------------------------------*/ + +int flash_erase (flash_info_t *info, int s_first, int s_last) +{ +    volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[0]); +    int flag, prot, sect, l_sect; +    ulong start, now, last; +    int rc = 0; + +    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_UNKNOWN) || +        (info->flash_id > FLASH_AMD_COMP)) { +        printf ("Can't erase unknown flash type - 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"); +    } + +    l_sect = -1; + +    /* Disable interrupts which might cause a timeout here */ +    flag = disable_interrupts(); + +    addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; +    addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; +    addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080; +    addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; +    addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + +    /* Start erase on unprotected sectors */ +    for (sect = s_first; sect<=s_last; sect++) { +        if (info->protect[sect] == 0) { /* not protected */ +            addr = (FLASH_WORD_SIZE *)(info->start[sect]); +            if (info->flash_id & FLASH_MAN_SST) { +                addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; +                addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; +                addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080; +                addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; +                addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; +                addr[0] = (FLASH_WORD_SIZE)0x00500050;  /* block erase */ +                udelay(30000);  /* wait 30 ms */ +            } +            else +                addr[0] = (FLASH_WORD_SIZE)0x00300030;  /* sector erase */ +            l_sect = sect; +        } +    } + +    /* re-enable interrupts if necessary */ +    if (flag) +        enable_interrupts(); + +    /* wait at least 80us - let's wait 1 ms */ +    udelay (1000); + +    /* +     * We wait for the last triggered sector +     */ +    if (l_sect < 0) +        goto DONE; + +    start = get_timer (0); +    last  = start; +    addr = (FLASH_WORD_SIZE *)(info->start[l_sect]); +    while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) { +        if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) { +            printf ("Timeout\n"); +            return 1; +        } +        /* show that we're waiting */ +        if ((now - last) > 1000) {  /* every second */ +            serial_putc ('.'); +            last = now; +        } +    } + +DONE: +    /* reset to read mode */ +    addr = (FLASH_WORD_SIZE *)info->start[0]; +    addr[0] = (FLASH_WORD_SIZE)0x00F000F0;  /* reset bank */ + +    printf (" done\n"); +    return rc; +} + +/*----------------------------------------------------------------------------*/ +/* + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ +    ulong cp, wp, data; +    int i, l, rc; + +    wp = (addr & ~3);   /* get lower word aligned address */ + +    /* +     * handle unaligned start bytes +     */ +    if ((l = addr - wp) != 0) { +        data = 0; +        for (i=0, cp=wp; i<l; ++i, ++cp) { +            data = (data << 8) | (*(uchar *)cp); +        } +        for (; i<4 && cnt>0; ++i) { +            data = (data << 8) | *src++; +            --cnt; +            ++cp; +        } +        for (; cnt==0 && i<4; ++i, ++cp) { +            data = (data << 8) | (*(uchar *)cp); +        } + +        if ((rc = write_word(info, wp, data)) != 0) { +            return (rc); +        } +        wp += 4; +    } + +    /* +     * handle word aligned part +     */ +    while (cnt >= 4) { +        data = 0; +        for (i=0; i<4; ++i) { +            data = (data << 8) | *src++; +        } +        if ((rc = write_word(info, wp, data)) != 0) { +            return (rc); +        } +        wp  += 4; +        cnt -= 4; +    } + +    if (cnt == 0) { +        return (0); +    } + +    /* +     * handle unaligned tail bytes +     */ +    data = 0; +    for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) { +        data = (data << 8) | *src++; +        --cnt; +    } +    for (; i<4; ++i, ++cp) { +        data = (data << 8) | (*(uchar *)cp); +    } + +    return (write_word(info, wp, data)); +} + +/*----------------------------------------------------------------------------*/ +/* Write a word to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static int write_word (flash_info_t *info, ulong dest, ulong data) +{ +        volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)(info->start[0]); +        volatile FLASH_WORD_SIZE *dest2 = (FLASH_WORD_SIZE *)dest; +        volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *)&data; +    ulong start; +    int flag; +        int i; + +    /* Check if Flash is (sufficiently) erased */ +    if ((*((volatile FLASH_WORD_SIZE *)dest) & +             (FLASH_WORD_SIZE)data) != (FLASH_WORD_SIZE)data) { +        return (2); +    } +    /* Disable interrupts which might cause a timeout here */ +    flag = disable_interrupts(); + +        for (i=0; i<4/sizeof(FLASH_WORD_SIZE); i++) +          { +            addr2[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; +            addr2[ADDR1] = (FLASH_WORD_SIZE)0x00550055; +            addr2[ADDR0] = (FLASH_WORD_SIZE)0x00A000A0; + +            dest2[i] = data2[i]; + +            /* re-enable interrupts if necessary */ +            if (flag) +              enable_interrupts(); + +            /* data polling for D7 */ +            start = get_timer (0); +            while ((dest2[i] & (FLASH_WORD_SIZE)0x00800080) != +                   (data2[i] & (FLASH_WORD_SIZE)0x00800080)) { +              if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { +                return (1); +              } +            } +          } + +    return (0); +} + +/*----------------------------------------------------------------------------*/ + diff --git a/board/eltec/bab7xx/l2cache.c b/board/eltec/bab7xx/l2cache.c new file mode 100644 index 000000000..748d515f4 --- /dev/null +++ b/board/eltec/bab7xx/l2cache.c @@ -0,0 +1,159 @@ +/* + * (C) Copyright 2002 ELTEC Elektronik AG + * Frank Gottschling <fgottschling@eltec.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> + +#if defined(CFG_L2_BAB7xx) + +#include <pci.h> +#include <mpc106.h> + +/* defines L2CR register for MPC750 */ + +#define L2CR_E           0x80000000 +#define L2CR_256K        0x10000000 +#define L2CR_512K        0x20000000 +#define L2CR_1024K       0x30000000 +#define L2CR_I           0x00200000 +#define L2CR_SL          0x00008000 +#define L2CR_IP          0x00000001 + +/*----------------------------------------------------------------------------*/ + +static int dummy (int dummy) +{ +    return (dummy+1); +} + +/*----------------------------------------------------------------------------*/ + +int l2_cache_enable (int l2control) +{ +    if (l2control)              /* BAB750 */ +    { +        mtspr(SPRN_L2CR, l2control); +        mtspr(SPRN_L2CR, (l2control | L2CR_I)); +        while (mfspr(SPRN_L2CR) & L2CR_IP) +            ; +        mtspr(SPRN_L2CR, (l2control | L2CR_E)); +        return (0); +    } +    else /* BAB740 */ +    { +        int picr1, picr2, mask; +        int picr2CacheSize, cacheSize; +        int *d; +        int devbusfn; +        u32 reg32; + +        devbusfn = pci_find_device(PCI_VENDOR_ID_MOTOROLA, +                                   PCI_DEVICE_ID_MOTOROLA_MPC106, 0); +        if (devbusfn == -1) +            return (-1); + +        pci_read_config_dword  (devbusfn, PCI_PICR2, ®32); +        reg32 &= ~PICR2_L2_EN; +        pci_write_config_dword (devbusfn, PCI_PICR2, reg32); + +        /* cache size */ +        if (*(volatile unsigned char *) (CFG_ISA_IO + 0x220) & 0x04) +        { +            /* cache size is 512 KB */ +            picr2CacheSize = PICR2_L2_SIZE_512K; +            cacheSize = 0x80000; +        } +        else +        { +            /* cache size is 256 KB */ +            picr2CacheSize = PICR2_L2_SIZE_256K; +            cacheSize = 0x40000; +        } + +        /* setup PICR1 */ +        mask = +        ~(PICR1_CF_BREAD_WS(1) | +          PICR1_CF_BREAD_WS(2) | +          PICR1_CF_CBA(0xff) | +          PICR1_CF_CACHE_1G | +          PICR1_CF_DPARK | +          PICR1_CF_APARK | +          PICR1_CF_L2_CACHE_MASK); + +        picr1 = +        (PICR1_CF_CBA(0x3f) | +         PICR1_CF_CACHE_1G | +         PICR1_CF_APARK | +         PICR1_CF_DPARK | +         PICR1_CF_L2_COPY_BACK); /* PICR1_CF_L2_WRITE_THROUGH */ + +        pci_read_config_dword  (devbusfn, PCI_PICR1, ®32); +        reg32 &= mask; +        reg32 |= picr1; +        pci_write_config_dword (devbusfn, PCI_PICR1, reg32); + +        /* +         * invalidate all L2 cache +         */ +        picr2 = +        (PICR2_CF_INV_MODE | +         PICR2_CF_HIT_HIGH | +         PICR2_CF_MOD_HIGH | +         PICR2_CF_L2_HIT_DELAY(1) | +         PICR2_CF_APHASE_WS(1) | +         picr2CacheSize); + +        pci_write_config_dword (devbusfn, PCI_PICR2, picr2); + +        /* +         * dummy transactions +         */ +        for (d=0; d<(int *)(2*cacheSize); d++) +            dummy(*d); + +        pci_write_config_dword (devbusfn, PCI_PICR2, +                                (picr2 | PICR2_CF_FLUSH_L2)); + +        /* setup PICR2 */ +        picr2 = +        (PICR2_CF_FAST_CASTOUT | +         PICR2_CF_WDATA | +         PICR2_CF_ADDR_ONLY_DISABLE | +         PICR2_CF_HIT_HIGH | +         PICR2_CF_MOD_HIGH | +         PICR2_L2_UPDATE_EN | +         PICR2_L2_EN | +         PICR2_CF_APHASE_WS(1) | +         PICR2_CF_DATA_RAM_PBURST | +         PICR2_CF_L2_HIT_DELAY(1) | +         PICR2_CF_SNOOP_WS(2) | +         picr2CacheSize); + +        pci_write_config_dword (devbusfn, PCI_PICR2, picr2); +    } +    return (0); +} + +/*----------------------------------------------------------------------------*/ + +#endif /* (CFG_L2_BAB7xx) */ + diff --git a/board/eltec/bab7xx/misc.c b/board/eltec/bab7xx/misc.c new file mode 100644 index 000000000..1b4376dcd --- /dev/null +++ b/board/eltec/bab7xx/misc.c @@ -0,0 +1,547 @@ +/* + * (C) Copyright 2002 ELTEC Elektronik AG + * Frank Gottschling <fgottschling@eltec.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 + */ + +/* includes */ +#include <common.h> +#include <linux/ctype.h> +#include <pci.h> +#include <net.h> +#include <mpc106.h> +#include <w83c553f.h> +#include "srom.h" + +/* imports  */ +extern char console_buffer[CFG_CBSIZE]; +extern int l2_cache_enable (int l2control); +extern void *nvram_read (void *dest, const short src, size_t count); +extern void nvram_write (short dest, const void *src, size_t count); + +/* globals */ +unsigned int ata_reset_time = 60; +unsigned int scsi_reset_time = 10; +unsigned int eltec_board; + +/* BAB750 uses SYM53C875(default) and BAB740 uses SYM53C860 + * values fixed after board identification + */ +unsigned short scsi_dev_id = PCI_DEVICE_ID_NCR_53C875; +unsigned int   scsi_max_scsi_id = 15; +unsigned char  scsi_sym53c8xx_ccf = 0x13; + +/*----------------------------------------------------------------------------*/ +/* + * handle sroms on BAB740/750 + * fix ether address + * L2 cache initialization + * ide dma control + */ +int misc_init_r (void) +{ +    revinfo eerev; +    u_char *ptr; +    u_int  i, l, initSrom, copyNv; +    char buf[256]; +    char hex[23] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, +             0, 0, 0, 0, 10, 11, 12, 13, 14, 15 }; +    pci_dev_t bdf; + +    char sromSYM[] = { +#ifdef TULIP_BUG +    /* 10BaseT, 100BaseTx no full duplex modes */ +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x08, +    0x02, 0x86, 0x02, 0x00, 0xaf, 0x08, 0xa5, 0x00, +    0x88, 0x04, 0x03, 0x27, 0x08, 0x25, 0x00, 0x61, +    0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xe8 +#endif +    /* 10BaseT, 10BaseT-FD, 100BaseTx, 100BaseTx-FD */ +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x08, +    0x04, 0x86, 0x02, 0x00, 0xaf, 0x08, 0xa5, 0x00, +    0x86, 0x02, 0x04, 0xaf, 0x08, 0xa5, 0x00, 0x88, +    0x04, 0x03, 0x27, 0x08, 0x25, 0x00, 0x61, 0x80, +    0x88, 0x04, 0x05, 0x27, 0x08, 0x25, 0x00, 0x61, +    0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x77 +    }; + +    char sromMII[] = { +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x5b, 0x00, +    0x2e, 0x4d, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x08, +    0x01, 0x95, 0x03, 0x00, 0x00, 0x04, 0x01, 0x08, +    0x00, 0x00, 0x02, 0x08, 0x02, 0x00, 0x00, 0x78, +    0xe0, 0x01, 0x00, 0x50, 0x00, 0x18, 0x80, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0x41 +    }; + +    /* +     * Check/Remake revision info +     */ +    initSrom = 0; +    copyNv   = 0; + +    /* read out current revision srom contens */ +    el_srom_load (0x0000, (u_char*)&eerev, sizeof(revinfo), +                SECOND_DEVICE, FIRST_BLOCK); + +    /* read out current nvram shadow image */ +    nvram_read (buf, CFG_NV_SROM_COPY_ADDR, CFG_SROM_SIZE); + +    if (strcmp (eerev.magic, "ELTEC") != 0) +    { +        /* srom is not initialized -> create a default revision info */ +        for (i = 0, ptr = (u_char *)&eerev; i < sizeof(revinfo); i++) +            *ptr++ = 0x00; +        strcpy(eerev.magic, "ELTEC"); +        eerev.revrev[0] = 1; +        eerev.revrev[1] = 0; +        eerev.size = 0x00E0; +        eerev.category[0] = 0x01; + +        /* node id from dead e128 as default */ +        eerev.etheraddr[0] = 0x00; +        eerev.etheraddr[1] = 0x00; +        eerev.etheraddr[2] = 0x5B; +        eerev.etheraddr[3] = 0x00; +        eerev.etheraddr[4] = 0x2E; +        eerev.etheraddr[5] = 0x4D; + +        /* cache config word for bab750 */ +        *(int*)&eerev.res[0] = CLK2P0TO1_1MB_PB_0P5DH; + +        initSrom = 1;  /* force dialog */ +        copyNv   = 1;  /* copy to nvram */ +    } + +    if ((copyNv == 0) &&   (el_srom_checksum((u_char*)&eerev, CFG_SROM_SIZE) != +                el_srom_checksum((u_char*)buf, CFG_SROM_SIZE))) +    { +        printf ("Invalid revision info copy in nvram !\n"); +        printf ("Press key:\n  <c> to copy current revision info to nvram.\n"); +        printf ("  <r> to reenter revision info.\n"); +        printf ("=> "); +        if (0 != readline (NULL)) +        { +            switch ((char)toupper(console_buffer[0])) +            { +            case 'C': +                copyNv = 1; +                break; +            case 'R': +                copyNv = 1; +                initSrom = 1; +                break; +            } +        } +    } + +    if (initSrom) +    { +        memcpy (buf, &eerev.revision[0][0], 14);     /* save all revision info */ +        printf ("Enter revision number (0-9): %c  ", eerev.revision[0][0]); +        if (0 != readline (NULL)) +        { +            eerev.revision[0][0] = (char)toupper(console_buffer[0]); +            memcpy (&eerev.revision[1][0], buf, 12); /* shift rest of rev info */ +        } + +        printf ("Enter revision character (A-Z): %c  ", eerev.revision[0][1]); +        if (1 == readline (NULL)) +        { +            eerev.revision[0][1] = (char)toupper(console_buffer[0]); +        } + +        printf ("Enter board name (V-XXXX-XXXX): %s  ", (char *)&eerev.board); +        if (11 == readline (NULL)) +        { +            for (i=0; i<11; i++) +                eerev.board[i] =  (char)toupper(console_buffer[i]); +            eerev.board[11] = '\0'; +        } + +        printf ("Enter serial number: %s ", (char *)&eerev.serial ); +        if (6 == readline (NULL)) +        { +            for (i=0; i<6; i++) +                eerev.serial[i] = console_buffer[i]; +            eerev.serial[6] = '\0'; +        } + +        printf ("Enter ether node ID with leading zero (HEX): %02x%02x%02x%02x%02x%02x  ", +            eerev.etheraddr[0], eerev.etheraddr[1], +            eerev.etheraddr[2], eerev.etheraddr[3], +            eerev.etheraddr[4], eerev.etheraddr[5]); +        if (12 == readline (NULL)) +        { +            for (i=0; i<12; i+=2) +            eerev.etheraddr[i>>1] = (char)(16*hex[toupper(console_buffer[i])-'0'] + +                               hex[toupper(console_buffer[i+1])-'0']); +        } + +        l = strlen ((char *)&eerev.text); +        printf("Add to text section (max 64 chr): %s ", (char *)&eerev.text ); +        if (0 != readline (NULL)) +        { +            for (i = l; i<63; i++) +                eerev.text[i] = console_buffer[i-l]; +            eerev.text[63] = '\0'; +        } + +        if (strstr ((char *)&eerev.board, "75") != NULL) +            eltec_board = 750; +        else +            eltec_board = 740; + +        if (eltec_board == 750) +        { +            if (CPU_TYPE == CPU_TYPE_750) +                *(int*)&eerev.res[0] = CLK2P0TO1_1MB_PB_0P5DH; +                else +                *(int*)&eerev.res[0] = CLK2P5TO1_1MB_PB_0P5DH; + +            printf("Enter L2Cache config word with leading zero (HEX): %08X  ", +                    *(int*)&eerev.res[0] ); +            if (0 != readline (NULL)) +            { +                for (i=0; i<7; i+=2) +                { +                    eerev.res[i>>1] = +                    (char)(16*hex[toupper(console_buffer[i])-'0'] + +                    hex[toupper(console_buffer[i+1])-'0']); +                } +            } + +            /* prepare network eeprom */ +            sromMII[20] = eerev.etheraddr[0]; +            sromMII[21] = eerev.etheraddr[1]; +            sromMII[22] = eerev.etheraddr[2]; +            sromMII[23] = eerev.etheraddr[3]; +            sromMII[24] = eerev.etheraddr[4]; +            sromMII[25] = eerev.etheraddr[5]; +            printf("\nSRom:  Writing DEC21143 MII info .. "); + +            if (dc_srom_store ((u_short *)sromMII) == -1) +                printf("FAILED\n"); +            else +                printf("OK\n"); +        } + +        if (eltec_board == 740) +        { +            *(int *)&eerev.res[0] = 0; +            sromSYM[20] = eerev.etheraddr[0]; +            sromSYM[21] = eerev.etheraddr[1]; +            sromSYM[22] = eerev.etheraddr[2]; +            sromSYM[23] = eerev.etheraddr[3]; +            sromSYM[24] = eerev.etheraddr[4]; +            sromSYM[25] = eerev.etheraddr[5]; +            printf("\nSRom:  Writing DEC21143 SYM info .. "); + +            if (dc_srom_store ((u_short *)sromSYM) == -1) +                printf("FAILED\n"); +            else +                printf("OK\n"); +        } + +        /* update CRC */ +        eerev.crc = el_srom_checksum((u_char *)eerev.board, eerev.size); + +        /* write new values */ +        printf("\nSRom:  Writing revision info ...... "); +        if (el_srom_store((BLOCK_SIZE-sizeof(revinfo)), (u_char *)&eerev, +                            sizeof(revinfo), SECOND_DEVICE, FIRST_BLOCK) == -1) +            printf("FAILED\n\n"); +        else +            printf("OK\n\n"); + +        /* write new values as shadow image to nvram */ +        nvram_write (CFG_NV_SROM_COPY_ADDR, (void *)&eerev, CFG_SROM_SIZE); + +    } /*if (initSrom) */ + +    /* copy current values as shadow image to nvram */ +    if (initSrom == 0 && copyNv == 1) +        nvram_write (CFG_NV_SROM_COPY_ADDR, (void *)&eerev, CFG_SROM_SIZE); + +    /* update environment */ +    sprintf (buf, "%02x:%02x:%02x:%02x:%02x:%02x", +            eerev.etheraddr[0], eerev.etheraddr[1], +            eerev.etheraddr[2], eerev.etheraddr[3], +            eerev.etheraddr[4], eerev.etheraddr[5]); +    setenv ("ethaddr", buf); + +    /* print actual board identification */ +    printf("Ident: %s  Ser %s  Rev %c%c\n", +            eerev.board, (char *)&eerev.serial, +            eerev.revision[0][0], eerev.revision[0][1]); + +    /* global board ident */ +    if (strstr ((char *)&eerev.board, "75") != NULL) +        eltec_board = 750; +    else +        eltec_board = 740; + +   /* +    * L2 cache configuration +    */ +#if defined(CFG_L2_BAB7xx) +    ptr = getenv("l2cache"); +    if (*ptr == '0') +    { +        printf ("Cache: L2 NOT activated on BAB%d\n", eltec_board); +    } +    else +    { +        printf ("Cache: L2 activated on BAB%d\n", eltec_board); +        l2_cache_enable(*(int*)&eerev.res[0]); +    } +#endif + +   /* +    * Reconfig ata reset timeout from environment +    */ +    if ((ptr = getenv ("ata_reset_time")) != NULL) +    { +        ata_reset_time = (int)simple_strtoul (ptr, NULL, 10); +    } +    else +    { +        sprintf (buf, "%d", ata_reset_time); +        setenv ("ata_reset_time", buf); +    } + +   /* +    * Reconfig scsi reset timeout from environment +    */ +    if ((ptr = getenv ("scsi_reset_time")) != NULL) +    { +        scsi_reset_time = (int)simple_strtoul (ptr, NULL, 10); +    } +    else +    { +        sprintf (buf, "%d", scsi_reset_time); +        setenv ("scsi_reset_time", buf); +    } + + +    if ((bdf = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553, 0)) > 0) +    { +        if (pci_find_device(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C860, 0) > 0) +        { +            /* BAB740 with SCSI=IRQ 11; SCC=IRQ 9; no IDE; NCR860 at 80 Mhz */ +            scsi_dev_id = PCI_DEVICE_ID_NCR_53C860; +            scsi_max_scsi_id = 7; +            scsi_sym53c8xx_ccf = 0x15; +            pci_write_config_byte (bdf, WINBOND_IDEIRCR, 0xb0); +        } + +        if ((ptr = getenv ("ide_dma_off")) != NULL) +        { +            u_long dma_off = simple_strtoul (ptr, NULL, 10); +            /* +            * setup user defined registers +            * s.a. linux/drivers/ide/sl82c105.c +            */ +            bdf |= PCI_BDF(0,0,1);            /* ide user reg at bdf function 1 */ +            if (dma_off & 1) +            { +                pci_write_config_byte (bdf, 0x46, 1); +                printf("IDE:   DMA off flag set: Bus 0 : Dev 0\n"); +            } +            if (dma_off & 2) +            { +                pci_write_config_byte (bdf, 0x4a, 1); +                printf("IDE:   DMA off flag set: Bus 0 : Dev 1\n"); +            } +            if (dma_off & 4) +            { +                pci_write_config_byte (bdf, 0x4e, 1); +                printf("IDE:   DMA off flag set: Bus 1 : Dev 0\n"); +            } +            if (dma_off & 8) +            { +                pci_write_config_byte (bdf, 0x52, 1); +                printf("IDE:   DMA off flag set: Bus 1 : Dev 1\n"); +            } +        } +    } +    return (0); +} + +/*----------------------------------------------------------------------------*/ +/* + * BAB740 uses KENDIN KS8761 modem chip with not common setup values + */ +#ifdef CONFIG_TULIP_SELECT_MEDIA + +/* Register bits. + */ +#define BMR_SWR         0x00000001      /* Software Reset */ +#define STS_TS          0x00700000      /* Transmit Process State */ +#define STS_RS          0x000e0000      /* Receive Process State */ +#define OMR_ST          0x00002000      /* Start/Stop Transmission Command */ +#define OMR_SR          0x00000002      /* Start/Stop Receive */ +#define OMR_PS          0x00040000      /* Port Select */ +#define OMR_SDP         0x02000000      /* SD Polarity - MUST BE ASSERTED */ +#define OMR_PM          0x00000080      /* Pass All Multicast */ +#define OMR_PR          0x00000040      /* Promiscuous Mode */ +#define OMR_PCS         0x00800000      /* PCS Function */ +#define OMR_TTM         0x00400000      /* Transmit Threshold Mode */ + +/* Ethernet chip registers. + */ +#define DE4X5_BMR       0x000           /* Bus Mode Register */ +#define DE4X5_TPD       0x008           /* Transmit Poll Demand Reg */ +#define DE4X5_RRBA      0x018           /* RX Ring Base Address Reg */ +#define DE4X5_TRBA      0x020           /* TX Ring Base Address Reg */ +#define DE4X5_STS       0x028           /* Status Register */ +#define DE4X5_OMR       0x030           /* Operation Mode Register */ +#define DE4X5_SISR      0x060           /* SIA Status Register */ +#define DE4X5_SICR      0x068           /* SIA Connectivity Register */ +#define DE4X5_TXRX      0x070           /* SIA Transmit and Receive Register */ +#define DE4X5_GPPR      0x078           /* General Purpose Port register */ +#define DE4X5_APROM      0x048          /* Ethernet Address PROM */ + +/*----------------------------------------------------------------------------*/ + +static int INL(struct eth_device* dev, u_long addr) +{ +    return le32_to_cpu(*(volatile u_long *)(addr + dev->iobase)); +} + +/*----------------------------------------------------------------------------*/ + +static void OUTL(struct eth_device* dev, int command, u_long addr) +{ +    *(volatile u_long *)(addr + dev->iobase) = cpu_to_le32(command); +} + +/*----------------------------------------------------------------------------*/ + +static void media_reg_init ( +    struct eth_device* dev, +    u32 csr14, +    u32 csr15_dir, +    u32 csr15_v0, +    u32 csr15_v1, +    u32 csr6 ) +{ +    OUTL(dev, 0, DE4X5_OMR);            /* CSR6  */ +    udelay(10 * 1000); +    OUTL(dev, 0, DE4X5_SICR);           /* CSR13 */ +    OUTL(dev, 1, DE4X5_SICR);           /* CSR13 */ +    udelay(10 * 1000); +    OUTL(dev, csr14, DE4X5_TXRX);       /* CSR14 */ +    OUTL(dev, csr15_dir, DE4X5_GPPR);   /* CSR15 */ +    OUTL(dev, csr15_v0,  DE4X5_GPPR);   /* CSR15 */ +    udelay(10 * 1000); +    OUTL(dev, csr15_v1,  DE4X5_GPPR);   /* CSR15 */ +    OUTL(dev, 0x00000301, DE4X5_SISR);  /* CSR12 */ +    OUTL(dev, csr6, DE4X5_OMR);         /* CSR6 */ +} + +/*----------------------------------------------------------------------------*/ + +void dc21x4x_select_media(struct eth_device* dev) +{ +    int i, status, ext; +    extern unsigned int eltec_board; + +    if (eltec_board == 740) +    { +        printf("SYM media select "); /* BAB740 */ +        /* start autoneg. with 10 mbit */ +        media_reg_init (dev, 0x3ffff, 0x08af0008, 0x00a10008, 0x00a50008, 0x02400080); +        ext = status = 0; +        for (i=0; i<2000+ext; i++) +        { +            status = INL(dev, DE4X5_SISR); +            udelay(1000); +            if (status & 0x2000) ext = 2000; +            if ((status & 0x7000) == 0x5000) break; +        } + +        /* autoneg. ok -> 100MB FD */ +        if ((status & 0x0100f000) == 0x0100d000) +        { +            media_reg_init (dev, 0x37f7f, 0x08270008, 0x00210008, 0x00250008, 0x03c40280); +            printf("100baseTx-FD\n"); +        } +        /* autoneg. ok -> 100MB HD */ +        else if ((status & 0x0080f000) == 0x0080d000) +        { +            media_reg_init (dev, 0x17f7f, 0x08270008, 0x00210008, 0x00250008, 0x03c40080); +            printf("100baseTx\n"); +        } +        /* autoneg. ok -> 10MB FD */ +        else if ((status & 0x0040f000) == 0x0040d000) +        { +            media_reg_init (dev, 0x07f7f, 0x08af0008, 0x00a10008, 0x00a50008, 0x02400280); +            printf("10baseT-FD\n"); +        } +        /* autoneg. fail -> 10MB HD */ +        else +        { +            media_reg_init (dev, 0x7f7f, 0x08af0008, 0x00a10008, 0x00a50008, +                        (OMR_SDP | OMR_TTM | OMR_PM)); +            printf("10baseT\n"); +        } +    } +    else +    { +        printf("MII media selected\n");                     /* BAB750 */ +        OUTL(dev, OMR_SDP | OMR_PS | OMR_PM, DE4X5_OMR);    /* CSR6 */ +    } +} +#endif /* CONFIG_TULIP_SELECT_MEDIA */ + +/*---------------------------------------------------------------------------*/ diff --git a/board/eltec/bab7xx/pci.c b/board/eltec/bab7xx/pci.c new file mode 100644 index 000000000..2fd8e13ca --- /dev/null +++ b/board/eltec/bab7xx/pci.c @@ -0,0 +1,120 @@ +/* + * (C) Copyright 2002 ELTEC Elektronik AG + * Frank Gottschling <fgottschling@eltec.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 + */ + +/* + * PCI initialisation for the MPC10x. + */ + +#include <common.h> +#include <pci.h> +#include <mpc106.h> + +#ifdef CONFIG_PCI + +struct pci_controller local_hose; + +void pci_init(void) +{ +    struct pci_controller* hose = (struct pci_controller *)&local_hose; +    u32 reg32; +    u16 reg16; + +    hose->first_busno = 0; +    hose->last_busno = 0xff; + +    pci_set_region(hose->regions + 0, +        CFG_PCI_MEMORY_BUS, +        CFG_PCI_MEMORY_PHYS, +    /* +    * Attention: pci_hose_phys_to_bus() failes in address compare, +    * so we need (CFG_PCI_MEMORY_SIZE-1) +    */ +        CFG_PCI_MEMORY_SIZE-1, +        PCI_REGION_MEM | PCI_REGION_MEMORY); + +    /* PCI memory space */ +    pci_set_region(hose->regions + 1, +        CFG_PCI_MEM_BUS, +        CFG_PCI_MEM_PHYS, +        CFG_PCI_MEM_SIZE, +        PCI_REGION_MEM); + +    /* ISA/PCI memory space */ +    pci_set_region(hose->regions + 2, +        CFG_ISA_MEM_BUS, +        CFG_ISA_MEM_PHYS, +        CFG_ISA_MEM_SIZE, +        PCI_REGION_MEM); + +    /* PCI I/O space */ +    pci_set_region(hose->regions + 3, +        CFG_PCI_IO_BUS, +        CFG_PCI_IO_PHYS, +        CFG_PCI_IO_SIZE, +        PCI_REGION_IO); + +    /* ISA/PCI I/O space */ +    pci_set_region(hose->regions + 4, +        CFG_ISA_IO_BUS, +        CFG_ISA_IO_PHYS, +        CFG_ISA_IO_SIZE, +        PCI_REGION_IO); + +    hose->region_count = 5; + +    pci_setup_indirect(hose, +        MPC106_REG_ADDR, +        MPC106_REG_DATA); + +    pci_register_hose(hose); + +    hose->last_busno = pci_hose_scan(hose); + +    /* Initialises the MPC10x PCI Configuration regs. */ +    pci_read_config_dword (PCI_BDF(0,0,0), PCI_PICR2, ®32); +    reg32 |= PICR2_CF_SNOOP_WS(3) | +             PICR2_CF_FLUSH_L2 | +             PICR2_CF_L2_HIT_DELAY(3) | +             PICR2_CF_APHASE_WS(3); +    reg32 &= ~(PICR2_L2_EN | PICR2_L2_UPDATE_EN); +    pci_write_config_dword (PCI_BDF(0,0,0), PCI_PICR2, reg32); + +    pci_read_config_word (PCI_BDF(0,0,0), PCI_COMMAND, ®16); +    reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; +    pci_write_config_word(PCI_BDF(0,0,0), PCI_COMMAND, reg16); + +    /* Clear non-reserved bits in status register */ +    pci_write_config_word(PCI_BDF(0,0,0), PCI_STATUS, 0xffff); + +    pci_read_config_dword (PCI_BDF(0,0,0), PCI_PICR1, ®32); +    reg32 |= PICR1_CF_CBA(63) | +             PICR1_CF_BREAD_WS(2) | +             PICR1_MCP_EN | +             PICR1_CF_DPARK | +             PICR1_PROC_TYPE_604 | +             PICR1_CF_LOOP_SNOOP | +             PICR1_CF_APARK; +    pci_write_config_dword (PCI_BDF(0,0,0), PCI_PICR1, reg32); +} + +#endif /* CONFIG_PCI */ diff --git a/board/eltec/bab7xx/srom.h b/board/eltec/bab7xx/srom.h new file mode 100644 index 000000000..7924bcd40 --- /dev/null +++ b/board/eltec/bab7xx/srom.h @@ -0,0 +1,102 @@ +/* + * (C) Copyright 2002 ELTEC Elektronik AG + * Frank Gottschling <fgottschling@eltec.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 + */ + +/* common srom defs */ +#define FIRST_DEVICE            0x00 +#define SECOND_DEVICE           0x04 +#define FIRST_BLOCK             0x00 +#define SECOND_BLOCK            0x02 +#define BLOCK_SIZE              0x100 +#define ERROR                   (-1) + +#define CLK2P0TO1_1MB_PB_0P5DH  0x79000100 +#define CLK2P5TO1_1MB_PB_0P5DH  0x7B000100 + +#define CPU_TYPE_740            0x08 +#define CPU_TYPE_750            0x08 +#define CPU_TYPE                ((get_pvr()>>16)&0xffff) + +#define ABS(x)                  ((x<0)?-x:x) +#define SROM_SHORT(pX)          (*(u8 *)(pX) | *((u8 *)(pX)+1) << 8) + +/* bab7xx ELTEC srom */ +#define I2C_BUS_DAT             (CFG_ISA_IO + 0x220) +#define I2C_BUS_DIR             (CFG_ISA_IO + 0x221) + +/* srom at mpc107 */ +#define MPC107_I2CADDR          (mpc107_eumb_addr + 0x3000)     /* address      */ +#define MPC107_I2CFDR           (mpc107_eumb_addr + 0x3004)     /* freq divider */ +#define MPC107_I2CCR            (mpc107_eumb_addr + 0x3008)     /* control      */ +#define MPC107_I2CSR            (mpc107_eumb_addr + 0x300c)     /* status       */ +#define MPC107_I2CDR            (mpc107_eumb_addr + 0x3010)     /* data         */ +#define MPC107_I2C_TIMEOUT      10000000 + +/* i82559 */ +#define EE_ADDR_BITS            6 +#define EE_SIZE                 0x40                            /* 0x40 words */ +#define EE_CHECKSUM             0xBABA + +/* dc21143 */ +#define DEC_SROM_SIZE           128 + + +/* + * structure of revision srom + */ +typedef struct  { +    char    magic[8];           /* 000 - Magic number */ +    char    revrev[2];          /* 008 - Revision of structure */ +    unsigned short size;        /* 00A - Size of CRC area */ +    unsigned long  crc;         /* 00C - CRC */ +    char    board[16];          /* 010 - Board Revision information */ +    char    option[4][16];      /* 020 - Option Revision information */ +    char    serial[8];          /* 060 - Board serial number */ +    char    etheraddr[6];       /* 068 - Ethernet node addresse */ +    char    reserved[2];        /* 06E - Reserved */ +    char    revision[7][2];     /* 070 - Revision codes */ +    char    category[2];        /* 07E - Category codes */ +    char    text[64];           /* 080 - Text field */ +    char    res[64];            /* 0C0 - Reserved */ +} revinfo; + +unsigned long el_srom_checksum (unsigned char *ptr, unsigned long size); +int el_srom_load  (unsigned char addr, unsigned char *buf, int cnt, +                   unsigned char device, unsigned char block); +int el_srom_store (unsigned char addr, unsigned char *buf, int cnt, +                   unsigned char device, unsigned char block); + +int mpc107_i2c_init (unsigned long eumb_addr, unsigned long divider); +int mpc107_i2c_read_byte (unsigned char device, unsigned char block, unsigned char offset); +int mpc107_i2c_write_byte (unsigned char device, unsigned char block, +                           unsigned char offset, unsigned char val); +int mpc107_srom_load (unsigned char addr, unsigned char *pBuf, int cnt, +                      unsigned char device, unsigned char block); +int mpc107_srom_store (unsigned char addr, unsigned char *pBuf, int cnt, +                       unsigned char device, unsigned char block); + +int dc_srom_load (unsigned short *dest); +int dc_srom_store (unsigned short *src); + +unsigned short eepro100_srom_checksum (unsigned short *sromdata); +void eepro100_srom_load (unsigned short *destination); +int  eepro100_srom_store (unsigned short *source); diff --git a/board/eltec/elppc/Makefile b/board/eltec/elppc/Makefile new file mode 100644 index 000000000..1ed1a24c4 --- /dev/null +++ b/board/eltec/elppc/Makefile @@ -0,0 +1,57 @@ +# +# (C) Copyright 2000 +# 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 pci.o misc.o mpc107_i2c.o eepro100_srom.o + +SOBJS	= asm_init.o + +$(LIB):	.depend $(OBJS) $(SOBJS) +	$(AR) crv $@ $^ + +clean: +	rm -f $(SOBJS) $(OBJS) + +distclean:	clean +	rm -f $(LIB) core *.bak .depend + +######################################################################### + +.depend:	Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) +		$(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### + + + + + + + + + diff --git a/board/eltec/elppc/config.mk b/board/eltec/elppc/config.mk new file mode 100644 index 000000000..aa463c5dc --- /dev/null +++ b/board/eltec/elppc/config.mk @@ -0,0 +1,26 @@ +# +# (C) Copyright 2000 +# 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 +# + +TEXT_BASE = 0xFFF00000 + +PLATFORM_CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE) diff --git a/board/eltec/elppc/flash.c b/board/eltec/elppc/flash.c new file mode 100644 index 000000000..5834c9999 --- /dev/null +++ b/board/eltec/elppc/flash.c @@ -0,0 +1,513 @@ +/* + * (C) Copyright 2000 + * 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 + */ + +/* + * 07-10-2002 Frank Gottschling: added 29F032 flash (ELPPC). + *        fixed monitor protection part + * + * 09-18-2001 Andreas Heppel: Reduced the code in here to the usage + *        of AMD's 29F040 and 29F016 flashes, since the BAB7xx does use + *        any other. + */ + +#include <common.h> +#include <asm/processor.h> +#include <asm/pci_io.h> + +flash_info_t    flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ + +ulong flash_get_size (vu_long *addr, flash_info_t *info); +static int write_word (flash_info_t *info, ulong dest, ulong data); + +/*flash command address offsets*/ + +#define ADDR0           (0x555) +#define ADDR1           (0x2AA) +#define ADDR3           (0x001) + +#define FLASH_WORD_SIZE unsigned char + +/*----------------------------------------------------------------------------*/ + +unsigned long flash_init (void) +{ +    unsigned long size1, size2; +    int i; + +    /* Init: no FLASHes known */ +    for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) +    { +        flash_info[i].flash_id = FLASH_UNKNOWN; +    } + +    /* initialise 1st flash */ +    size1 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]); + +    if (flash_info[0].flash_id == FLASH_UNKNOWN) +    { +        printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n", +            size1, size1<<20); +    } + +    /* initialise 2nd flash */ +    size2 = flash_get_size((vu_long *)FLASH_BASE1_PRELIM, &flash_info[1]); + +    if (flash_info[1].flash_id == FLASH_UNKNOWN) +    { +        printf ("## Unknown FLASH on Bank 1 - Size = 0x%08lx = %ld MB\n", +            size2, size2<<20); +    } + +    /* monitor protection ON by default */ +    if (size1 == 512*1024) +    { +        (void)flash_protect(FLAG_PROTECT_SET, +                FLASH_BASE0_PRELIM, +                FLASH_BASE0_PRELIM+CFG_MONITOR_LEN-1, +                &flash_info[0]); +    } +    if (size2 == 512*1024) +    { +        (void)flash_protect(FLAG_PROTECT_SET, +                FLASH_BASE1_PRELIM, +                FLASH_BASE1_PRELIM+CFG_MONITOR_LEN-1, +                &flash_info[1]); +    } +    if (size2 == 4*1024*1024) +    { +        (void)flash_protect(FLAG_PROTECT_SET, +                CFG_FLASH_BASE, +                CFG_FLASH_BASE+CFG_MONITOR_LEN-1, +                &flash_info[1]); +    } + +    return (size1 + size2); +} + +/*----------------------------------------------------------------------------*/ + +void flash_print_info  (flash_info_t *info) +{ +    int i; +    int k; +    int size; +    int erased; +    volatile unsigned long *flash; + +    if (info->flash_id == FLASH_UNKNOWN) { +        printf ("missing or unknown FLASH type\n"); +        flash_init(); +    } + +    if (info->flash_id == FLASH_UNKNOWN) { +        printf ("missing or unknown FLASH type\n"); +        return; +    } + +    switch (info->flash_id & FLASH_VENDMASK) { +    case FLASH_MAN_AMD: +        printf ("AMD "); +        break; +    default: +        printf ("Unknown Vendor "); +        break; +    } + +    switch (info->flash_id & FLASH_TYPEMASK) { +    case AMD_ID_F040B: +        printf ("AM29F040B (4 Mbit)\n"); +        break; +    case AMD_ID_F016D: +        printf ("AM29F016D (16 Mbit)\n"); +        break; +    case AMD_ID_F032B: +        printf ("AM29F032B (32 Mbit)\n"); +        break; +   default: +        printf ("Unknown Chip Type\n"); +        break; +    } + +    if (info->size >= (1 << 20)) { +        printf ("  Size: %ld MB in %d Sectors\n", info->size >> 20, info->sector_count); +    } else { +        printf ("  Size: %ld kB in %d Sectors\n", info->size >> 10, info->sector_count); +    } + +    printf ("  Sector Start Addresses:"); +    for (i=0; i<info->sector_count; ++i) { +        /* +        * Check if whole sector is erased +        */ +        if (i != (info->sector_count-1)) +            size = info->start[i+1] - info->start[i]; +        else +            size = info->start[0] + info->size - info->start[i]; + +        erased = 1; +        flash = (volatile unsigned long *)info->start[i]; +        size = size >> 2;        /* divide by 4 for longword access */ +        for (k=0; k<size; k++) { +            if (*flash++ != 0xffffffff) { +                erased = 0; +                break; +            } +        } + +        if ((i % 5) == 0) +            printf ("\n   "); + +        printf (" %08lX%s%s", +            info->start[i], +            erased ? " E" : "  ", +            info->protect[i] ? "RO " : "   "); +    } +    printf ("\n"); +} + +/*----------------------------------------------------------------------------*/ +/* + * The following code cannot be run from FLASH! + */ +ulong flash_get_size (vu_long *addr, flash_info_t *info) +{ +    short i; +    ulong vendor, devid; +    ulong base = (ulong)addr; +    volatile unsigned char *caddr = (unsigned char *)addr; + +#ifdef DEBUG +    printf("flash_get_size for address 0x%lx: \n", (unsigned long)caddr); +#endif + +    /* Write auto select command: read Manufacturer ID */ +    caddr[0] = 0xF0;   /* reset bank */ +    udelay(10); + +    eieio(); +    caddr[0x555] = 0xAA; +    udelay(10); +    caddr[0x2AA] = 0x55; +    udelay(10); +    caddr[0x555] = 0x90; + +    udelay(10); + +    vendor = caddr[0]; +    devid = caddr[1]; + +#ifdef DEBUG +    printf("Manufacturer: 0x%lx\n", vendor); +#endif + +    vendor &= 0xff; +    devid &= 0xff; + +    /* We accept only two AMD types */ +    switch (vendor) { +    case (FLASH_WORD_SIZE)AMD_MANUFACT: +        info->flash_id = FLASH_MAN_AMD; +        break; +    default: +        info->flash_id = FLASH_UNKNOWN; +        info->sector_count = 0; +        info->size = 0; +        return (0);         /* no or unknown flash  */ +    } + +    switch (devid) { +    case (FLASH_WORD_SIZE)AMD_ID_F040B: +        info->flash_id |= AMD_ID_F040B; +        info->sector_count = 8; +        info->size = 0x00080000; +        break;              /* => 0.5 MB      */ + +    case (FLASH_WORD_SIZE)AMD_ID_F016D: +        info->flash_id |= AMD_ID_F016D; +        info->sector_count = 32; +        info->size         = 0x00200000; +        break;              /* => 2 MB      */ + +    case (FLASH_WORD_SIZE)AMD_ID_F032B: +        info->flash_id |= AMD_ID_F032B; +        info->sector_count = 64; +        info->size         = 0x00400000; +        break;              /* => 4 MB      */ + +    default: +        info->flash_id = FLASH_UNKNOWN; +        return (0);         /* => no or unknown flash */ + +    } + +#ifdef DEBUG +    printf("flash id 0x%lx; sector count 0x%x, size 0x%lx\n", info->flash_id, info->sector_count, info->size); +#endif + +    /* check for protected sectors */ +    for (i = 0; i < info->sector_count; i++) { +        /* sector base address */ +        info->start[i] = base + i * (info->size / info->sector_count); +        /* read sector protection at sector address, (A7 .. A0) = 0x02 */ +        /* D0 = 1 if protected */ +        caddr = (volatile unsigned char *)(info->start[i]); +        info->protect[i] = caddr[2] & 1; +    } + +    /* +     * Prevent writes to uninitialized FLASH. +     */ +    if (info->flash_id != FLASH_UNKNOWN) { +        caddr = (volatile unsigned char *)info->start[0]; +        caddr[0] = 0xF0;   /* reset bank */ +    } + +    return (info->size); +} + +/*----------------------------------------------------------------------------*/ + +int flash_erase (flash_info_t *info, int s_first, int s_last) +{ +    volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[0]); +    int flag, prot, sect, l_sect; +    ulong start, now, last; +    int rc = 0; + +    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_UNKNOWN) || +        (info->flash_id > FLASH_AMD_COMP)) { +        printf ("Can't erase unknown flash type - 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"); +    } + +    l_sect = -1; + +    /* Disable interrupts which might cause a timeout here */ +    flag = disable_interrupts(); + +    addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; +    addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; +    addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080; +    addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; +    addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + +    /* Start erase on unprotected sectors */ +    for (sect = s_first; sect<=s_last; sect++) { +        if (info->protect[sect] == 0) { /* not protected */ +            addr = (FLASH_WORD_SIZE *)(info->start[sect]); +            if (info->flash_id & FLASH_MAN_SST) { +                addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; +                addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; +                addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080; +                addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; +                addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; +                addr[0] = (FLASH_WORD_SIZE)0x00500050;  /* block erase */ +                udelay(30000);  /* wait 30 ms */ +            } +            else +                addr[0] = (FLASH_WORD_SIZE)0x00300030;  /* sector erase */ +            l_sect = sect; +        } +    } + +    /* re-enable interrupts if necessary */ +    if (flag) +        enable_interrupts(); + +    /* wait at least 80us - let's wait 1 ms */ +    udelay (1000); + +    /* +     * We wait for the last triggered sector +     */ +    if (l_sect < 0) +        goto DONE; + +    start = get_timer (0); +    last  = start; +    addr = (FLASH_WORD_SIZE *)(info->start[l_sect]); +    while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) { +        if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) { +            printf ("Timeout\n"); +            return 1; +        } +        /* show that we're waiting */ +        if ((now - last) > 1000) {  /* every second */ +            serial_putc ('.'); +            last = now; +        } +    } + +DONE: +    /* reset to read mode */ +    addr = (FLASH_WORD_SIZE *)info->start[0]; +    addr[0] = (FLASH_WORD_SIZE)0x00F000F0;  /* reset bank */ + +    printf (" done\n"); +    return rc; +} + +/*----------------------------------------------------------------------------*/ +/* + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ +    ulong cp, wp, data; +    int i, l, rc; + +    wp = (addr & ~3);   /* get lower word aligned address */ + +    /* +     * handle unaligned start bytes +     */ +    if ((l = addr - wp) != 0) { +        data = 0; +        for (i=0, cp=wp; i<l; ++i, ++cp) { +            data = (data << 8) | (*(uchar *)cp); +        } +        for (; i<4 && cnt>0; ++i) { +            data = (data << 8) | *src++; +            --cnt; +            ++cp; +        } +        for (; cnt==0 && i<4; ++i, ++cp) { +            data = (data << 8) | (*(uchar *)cp); +        } + +        if ((rc = write_word(info, wp, data)) != 0) { +            return (rc); +        } +        wp += 4; +    } + +    /* +     * handle word aligned part +     */ +    while (cnt >= 4) { +        data = 0; +        for (i=0; i<4; ++i) { +            data = (data << 8) | *src++; +        } +        if ((rc = write_word(info, wp, data)) != 0) { +            return (rc); +        } +        wp  += 4; +        cnt -= 4; +    } + +    if (cnt == 0) { +        return (0); +    } + +    /* +     * handle unaligned tail bytes +     */ +    data = 0; +    for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) { +        data = (data << 8) | *src++; +        --cnt; +    } +    for (; i<4; ++i, ++cp) { +        data = (data << 8) | (*(uchar *)cp); +    } + +    return (write_word(info, wp, data)); +} + +/*----------------------------------------------------------------------------*/ +/* Write a word to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static int write_word (flash_info_t *info, ulong dest, ulong data) +{ +        volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)(info->start[0]); +        volatile FLASH_WORD_SIZE *dest2 = (FLASH_WORD_SIZE *)dest; +        volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *)&data; +    ulong start; +    int flag; +        int i; + +    /* Check if Flash is (sufficiently) erased */ +    if ((*((volatile FLASH_WORD_SIZE *)dest) & +             (FLASH_WORD_SIZE)data) != (FLASH_WORD_SIZE)data) { +        return (2); +    } +    /* Disable interrupts which might cause a timeout here */ +    flag = disable_interrupts(); + +        for (i=0; i<4/sizeof(FLASH_WORD_SIZE); i++) +          { +            addr2[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; +            addr2[ADDR1] = (FLASH_WORD_SIZE)0x00550055; +            addr2[ADDR0] = (FLASH_WORD_SIZE)0x00A000A0; + +            dest2[i] = data2[i]; + +            /* re-enable interrupts if necessary */ +            if (flag) +              enable_interrupts(); + +            /* data polling for D7 */ +            start = get_timer (0); +            while ((dest2[i] & (FLASH_WORD_SIZE)0x00800080) != +                   (data2[i] & (FLASH_WORD_SIZE)0x00800080)) { +              if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { +                return (1); +              } +            } +          } + +    return (0); +} + +/*----------------------------------------------------------------------------*/ + diff --git a/board/eltec/elppc/misc.c b/board/eltec/elppc/misc.c new file mode 100644 index 000000000..7bfb3a493 --- /dev/null +++ b/board/eltec/elppc/misc.c @@ -0,0 +1,258 @@ +/* + * (C) Copyright 2002 ELTEC Elektronik AG + * Frank Gottschling <fgottschling@eltec.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 + */ + +/* includes */ +#include <common.h> +#include <linux/ctype.h> +#include <pci.h> +#include <net.h> +#include "srom.h" + +/* imports  */ +extern char console_buffer[CFG_CBSIZE]; +extern int l2_cache_enable (int l2control); +extern int eepro100_write_eeprom (struct eth_device* dev, int location, +                 int addr_len, unsigned short data); +extern int read_eeprom (struct eth_device* dev, int location, int addr_len); + +/*----------------------------------------------------------------------------*/ +/* + * read/write to nvram is only byte access + */ +void *nvram_read(void *dest, const long src, size_t count) +{ +    uchar *d = (uchar *) dest; +    uchar *s = (uchar *) (CFG_ENV_MAP_ADRS + src); + +    while (count--) +        *d++ = *s++; + +    return dest; +} + +void nvram_write(long dest, const void *src, size_t count) +{ +    uchar *d = (uchar *) (CFG_ENV_MAP_ADRS + dest); +    uchar *s = (uchar *) src; + +    while (count--) +        *d++ = *s++; +} + +/*----------------------------------------------------------------------------*/ +/* + * handle sroms on ELPPC + * fix ether address + * set serial console as default + */ +int misc_init_r (void) +{ +    revinfo eerev; +    u_char *ptr; +    u_int  i, l, initSrom, copyNv; +    char buf[256]; +    char hex[23] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, +                     0, 0, 0, 0, 10, 11, 12, 13, 14, 15 }; + +    /* Clock setting for MPC107 i2c */ +    mpc107_i2c_init (MPC107_EUMB_ADDR, 0x2b); + +    /* Reset the EPIC */ +    out32r (MPC107_EUMB_GCR, 0xa0000000); +    while (in32r (MPC107_EUMB_GCR) & 0x80000000);   /* Wait for reset to complete */ +    out32r (MPC107_EUMB_GCR, 0x20000000);           /* Put into into mixed mode */ +    while (in32r (MPC107_EUMB_IACKR) != 0xff);      /* Clear all pending interrupts */ + +    /* +     * Check/Remake revision info +     */ +    initSrom = 0; +    copyNv   = 0; + +    /* read out current revision srom contens */ +    mpc107_srom_load (0x0000, (u_char*)&eerev, sizeof(revinfo), +                SECOND_DEVICE, FIRST_BLOCK); + +    /* read out current nvram shadow image */ +    nvram_read (buf, CFG_NV_SROM_COPY_ADDR, CFG_SROM_SIZE); + +    if (strcmp (eerev.magic, "ELTEC") != 0) +    { +        /* srom is not initialized -> create a default revision info */ +        for (i = 0, ptr = (u_char *)&eerev; i < sizeof(revinfo); i++) +            *ptr++ = 0x00; +        strcpy(eerev.magic, "ELTEC"); +        eerev.revrev[0] = 1; +        eerev.revrev[1] = 0; +        eerev.size = 0x00E0; +        eerev.category[0] = 0x01; + +        /* node id from dead e128 as default */ +        eerev.etheraddr[0] = 0x00; +        eerev.etheraddr[1] = 0x00; +        eerev.etheraddr[2] = 0x5B; +        eerev.etheraddr[3] = 0x00; +        eerev.etheraddr[4] = 0x2E; +        eerev.etheraddr[5] = 0x4D; + +        /* cache config word for ELPPC */ +        *(int*)&eerev.res[0] = 0; + +        initSrom = 1;  /* force dialog */ +        copyNv   = 1;  /* copy to nvram */ +    } + +    if ((copyNv == 0) &&   (el_srom_checksum((u_char*)&eerev, CFG_SROM_SIZE) != +                el_srom_checksum((u_char*)buf, CFG_SROM_SIZE))) +    { +        printf ("Invalid revision info copy in nvram !\n"); +        printf ("Press key:\n  <c> to copy current revision info to nvram.\n"); +        printf ("  <r> to reenter revision info.\n"); +        printf ("=> "); +        if (0 != readline (NULL)) +        { +            switch ((char)toupper(console_buffer[0])) +            { +            case 'C': +                copyNv = 1; +                break; +            case 'R': +                copyNv = 1; +                initSrom = 1; +                break; +            } +        } +    } + +    if (initSrom) +    { +        memcpy (buf, &eerev.revision[0][0], 14);     /* save all revision info */ +        printf ("Enter revision number (0-9): %c  ", eerev.revision[0][0]); +        if (0 != readline (NULL)) +        { +            eerev.revision[0][0] = (char)toupper(console_buffer[0]); +            memcpy (&eerev.revision[1][0], buf, 12); /* shift rest of rev info */ +        } + +        printf ("Enter revision character (A-Z): %c  ", eerev.revision[0][1]); +        if (1 == readline (NULL)) +        { +            eerev.revision[0][1] = (char)toupper(console_buffer[0]); +        } + +        printf ("Enter board name (V-XXXX-XXXX): %s  ", (char *)&eerev.board); +        if (11 == readline (NULL)) +        { +            for (i=0; i<11; i++) +                eerev.board[i] =  (char)toupper(console_buffer[i]); +            eerev.board[11] = '\0'; +        } + +        printf ("Enter serial number: %s ", (char *)&eerev.serial ); +        if (6 == readline (NULL)) +        { +            for (i=0; i<6; i++) +                eerev.serial[i] = console_buffer[i]; +            eerev.serial[6] = '\0'; +        } + +        printf ("Enter ether node ID with leading zero (HEX): %02x%02x%02x%02x%02x%02x  ", +            eerev.etheraddr[0], eerev.etheraddr[1], +            eerev.etheraddr[2], eerev.etheraddr[3], +            eerev.etheraddr[4], eerev.etheraddr[5]); +        if (12 == readline (NULL)) +        { +            for (i=0; i<12; i+=2) +            eerev.etheraddr[i>>1] = (char)(16*hex[toupper(console_buffer[i])-'0'] + +                               hex[toupper(console_buffer[i+1])-'0']); +        } + +        l = strlen ((char *)&eerev.text); +        printf("Add to text section (max 64 chr): %s ", (char *)&eerev.text ); +        if (0 != readline (NULL)) +        { +            for (i = l; i<63; i++) +                eerev.text[i] = console_buffer[i-l]; +            eerev.text[63] = '\0'; +        } + +        /* prepare network eeprom */ +        memset (buf, 0, 128); + +        buf[0] = eerev.etheraddr[1]; +        buf[1] = eerev.etheraddr[0]; +        buf[2] = eerev.etheraddr[3]; +        buf[3] = eerev.etheraddr[2]; +        buf[4] = eerev.etheraddr[5]; +        buf[5] = eerev.etheraddr[4]; + +        *(unsigned short *)&buf[20] = 0x48B2; +        *(unsigned short *)&buf[22] = 0x0004; +        *(unsigned short *)&buf[24] = 0x1433; + +        printf("\nSRom:  Writing i82559 info ........ "); +        if (eepro100_srom_store ((unsigned short *)buf) == -1) +            printf("FAILED\n"); +        else +            printf("OK\n"); + +        /* update CRC */ +        eerev.crc = el_srom_checksum((u_char *)eerev.board, eerev.size); + +        /* write new values */ +        printf("\nSRom:  Writing revision info ...... "); +        if (mpc107_srom_store((BLOCK_SIZE-sizeof(revinfo)), (u_char *)&eerev, +                            sizeof(revinfo), SECOND_DEVICE, FIRST_BLOCK) == -1) +            printf("FAILED\n\n"); +        else +            printf("OK\n\n"); + +        /* write new values as shadow image to nvram */ +        nvram_write (CFG_NV_SROM_COPY_ADDR, (void *)&eerev, CFG_SROM_SIZE); + +    } /*if (initSrom) */ + +    /* copy current values as shadow image to nvram */ +    if (initSrom == 0 && copyNv == 1) +        nvram_write (CFG_NV_SROM_COPY_ADDR, (void *)&eerev, CFG_SROM_SIZE); + +    /* update environment */ +    sprintf (buf, "%02x:%02x:%02x:%02x:%02x:%02x", +            eerev.etheraddr[0], eerev.etheraddr[1], +            eerev.etheraddr[2], eerev.etheraddr[3], +            eerev.etheraddr[4], eerev.etheraddr[5]); +    setenv ("ethaddr", buf); + +    /* set serial console as default */ +    if ((ptr = getenv ("console")) == NULL) +        setenv ("console", "serial"); + +    /* print actual board identification */ +    printf("Ident: %s  Ser %s  Rev %c%c\n", +            eerev.board, (char *)&eerev.serial, +            eerev.revision[0][0], eerev.revision[0][1]); + +    return (0); +} + +/*----------------------------------------------------------------------------*/ diff --git a/board/eltec/elppc/mpc107_i2c.c b/board/eltec/elppc/mpc107_i2c.c new file mode 100644 index 000000000..a4bf5992d --- /dev/null +++ b/board/eltec/elppc/mpc107_i2c.c @@ -0,0 +1,320 @@ +/* + * (C) Copyright 2002 ELTEC Elektronik AG + * Frank Gottschling <fgottschling@eltec.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 + */ + +/* includes */ +#include <common.h> +#include "srom.h" + +/* locals */ +static unsigned long mpc107_eumb_addr = 0; + +/*----------------------------------------------------------------------------*/ + +/* + * calculate checksum for ELTEC revision srom + */ +unsigned long el_srom_checksum (ptr, size) +register unsigned char *ptr; +unsigned long size; +{ +    u_long f, accu = 0; +    u_int  i; +    u_char byte; + +    for (; size; size--) +    { +        byte = *ptr++; +        for (i = 8; i; i--) +        { +            f =  ((byte & 1) ^ (accu & 1)) ? 0x84083001 : 0; +            accu >>= 1; accu ^= f; +            byte >>= 1; +        } +    } +    return(accu); +} + +/*----------------------------------------------------------------------------*/ + +static int mpc107_i2c_wait ( unsigned long timeout ) +{ +    unsigned long x; + +    while (((x = in32r(MPC107_I2CSR)) & 0x82) != 0x82) +    { +        if (!timeout--) +            return -1; +    } + +    if (x & 0x10) +    { +        return -1; +    } +    out32r(MPC107_I2CSR, 0); + +    return 0; +} + +/*----------------------------------------------------------------------------*/ + +static int mpc107_i2c_wait_idle ( unsigned long timeout ) +{ +    while (in32r(MPC107_I2CSR) & 0x20) +    { +        if (!timeout--) +            return -1; +    } +    return 0; +} + + +/*----------------------------------------------------------------------------*/ + +int mpc107_i2c_read_byte ( +    unsigned char device, +    unsigned char block, +    unsigned char offset ) +{ +    unsigned long timeout = MPC107_I2C_TIMEOUT; +    int data; + +    if (!mpc107_eumb_addr) +        return -6; + +    mpc107_i2c_wait_idle (timeout); + +    /* Start with MEN */ +    out32r(MPC107_I2CCR, 0x80); + +    /* Start as master */ +    out32r(MPC107_I2CCR, 0xB0); +    out32r(MPC107_I2CDR, (0xA0 | device | block)); + +    if (mpc107_i2c_wait(timeout) < 0) +    { +        printf("mpc107_i2c_read Error 1\n"); +        return -2; +    } + +    if (in32r(MPC107_I2CSR)&0x1) +    { +        /* Generate STOP condition; device busy or not existing */ +        out32r(MPC107_I2CCR, 0x80); +        return -1; +    } + +    /* Data address */ +    out32r(MPC107_I2CDR, offset); + +    if (mpc107_i2c_wait(timeout) < 0) +    { +        printf("mpc107_i2c_read Error 2\n"); +        return -3; +    } + +    /* Switch to read - restart */ +    out32r(MPC107_I2CCR, 0xB4); +    out32r(MPC107_I2CDR, (0xA1 | device | block)); + +    if (mpc107_i2c_wait(timeout) < 0) +    { +        printf("mpc107_i2c_read Error 3\n"); +        return -4; +    } + +    out32r(MPC107_I2CCR, 0xA8); /* no ACK */ +    in32r(MPC107_I2CDR); + +    if (mpc107_i2c_wait(timeout) < 0) +    { +        printf("mpc107_i2c_read Error 4\n"); +        return -5; +    } +    /* Generate STOP condition */ +    out32r(MPC107_I2CCR, 0x88); + +    /* read */ +    data = in32r(MPC107_I2CDR); + +    return (data); +} + +/*----------------------------------------------------------------------------*/ + +int mpc107_i2c_write_byte ( +    unsigned char device, +    unsigned char block, +    unsigned char offset, +    unsigned char val ) +{ + +    unsigned long timeout = MPC107_I2C_TIMEOUT; + +    if (!mpc107_eumb_addr) +        return -6; + +    mpc107_i2c_wait_idle(timeout); + +    /* Start with MEN */ +    out32r(MPC107_I2CCR, 0x80); + +    /* Start as master */ +    out32r(MPC107_I2CCR, 0xB0); +    out32r(MPC107_I2CDR, (0xA0 | device | block)); + +    if (mpc107_i2c_wait(timeout) < 0) +    { +        printf("mpc107_i2c_write Error 1\n"); +        return -1; +    } + +    /* Data address */ +    out32r(MPC107_I2CDR, offset); + +    if (mpc107_i2c_wait(timeout) < 0) +    { +        printf("mpc107_i2c_write Error 2\n"); +        return -1; +    } + +    /* Write */ +    out32r(MPC107_I2CDR, val); +    if (mpc107_i2c_wait(timeout) < 0) +    { +        printf("mpc107_i2c_write Error 3\n"); +        return -1; +    } + +    /* Generate Stop Condition */ +    out32r(MPC107_I2CCR, 0x80); + +    /* Return ACK or no ACK */ +    return (in32r(MPC107_I2CSR) & 0x01); +} + +/*----------------------------------------------------------------------------*/ + +int mpc107_srom_load ( +    unsigned char addr, +    unsigned char *pBuf, +    int          cnt, +    unsigned char device, +    unsigned char block ) +{ +    register int i; +    int val; +    int timeout; + +    for (i = 0; i < cnt; i++) +    { +        timeout=100; +        do +        { +            val = mpc107_i2c_read_byte (device, block, addr); +            if (val < -1) +            { +            printf("i2c_read_error %d at dev %x block %x addr %x\n", +                   val, device, block, addr); +            return -1; +            } +            else if (timeout==0) +            { +                printf ("i2c_read_error: timeout at dev %x block %x addr %x\n", +                        device, block, addr); +                return -1; +            } +            timeout--; +        } while (val == -1); /* if no ack: try again! */ + +        *pBuf++ = (unsigned char)val; +        addr++; + +        if ((addr == 0) && (i != cnt-1))    /* is it the same block ? */ +        { +            if (block == FIRST_BLOCK) +                block = SECOND_BLOCK; +            else +            { +                printf ("ic2_read_error: read beyond 2. block !\n"); +                return -1; +            } +        } +    } +    udelay(100000); +    return (cnt); +} + +/*----------------------------------------------------------------------------*/ + +int mpc107_srom_store ( +    unsigned char addr, +    unsigned char *pBuf, +    int          cnt, +    unsigned char device, +    unsigned char block ) +{ +    register int i; + +    for (i = 0; i < cnt; i++) +    { +        while (mpc107_i2c_write_byte (device,block,addr,*pBuf) == 1); +        addr++; +        pBuf++; + +        if ((addr == 0) && (i != cnt-1))     /* is it the same block ? */ +        { +            if (block == FIRST_BLOCK) +                block = SECOND_BLOCK; +            else +            { +                printf ("ic2_write_error: write beyond 2. block !\n"); +                return -1; +            } +        } +    } +    udelay(100000); +    return(cnt); +} + +/*----------------------------------------------------------------------------*/ + +int mpc107_i2c_init ( unsigned long eumb_addr, unsigned long divider ) +{ +    unsigned long x; + +    if (eumb_addr) +        mpc107_eumb_addr = eumb_addr; +    else +        return -1; + +    /* Set I2C clock */ +    x = in32r(MPC107_I2CFDR) & 0xffffff00; +    out32r(MPC107_I2CFDR, (x | divider)); + +    /* Clear arbitration */ +    out32r(MPC107_I2CSR, 0); + +    return mpc107_eumb_addr; +} + +/*----------------------------------------------------------------------------*/ diff --git a/board/eltec/elppc/pci.c b/board/eltec/elppc/pci.c new file mode 100644 index 000000000..07158e678 --- /dev/null +++ b/board/eltec/elppc/pci.c @@ -0,0 +1,97 @@ +/* + * (C) Copyright 2002 ELTEC Elektronik AG + * Frank Gottschling <fgottschling@eltec.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 + */ + +/* + * PCI initialisation for the MPC10x. + */ + +#include <common.h> +#include <pci.h> +#include <mpc106.h> + +#ifdef CONFIG_PCI + +struct pci_controller local_hose; + +void pci_init(void) +{ +    struct pci_controller* hose = (struct pci_controller *)&local_hose; +    u16 reg16; + +    hose->first_busno = 0; +    hose->last_busno = 0xff; + +    pci_set_region(hose->regions + 0, +        CFG_PCI_MEMORY_BUS, +        CFG_PCI_MEMORY_PHYS, +        CFG_PCI_MEMORY_SIZE, +        PCI_REGION_MEM | PCI_REGION_MEMORY); + +    /* PCI memory space */ +    pci_set_region(hose->regions + 1, +        CFG_PCI_MEM_BUS, +        CFG_PCI_MEM_PHYS, +        CFG_PCI_MEM_SIZE, +        PCI_REGION_MEM); + +    /* ISA/PCI memory space */ +    pci_set_region(hose->regions + 2, +        CFG_ISA_MEM_BUS, +        CFG_ISA_MEM_PHYS, +        CFG_ISA_MEM_SIZE, +        PCI_REGION_MEM); + +    /* PCI I/O space */ +    pci_set_region(hose->regions + 3, +        CFG_PCI_IO_BUS, +        CFG_PCI_IO_PHYS, +        CFG_PCI_IO_SIZE, +        PCI_REGION_IO); + +    /* ISA/PCI I/O space */ +    pci_set_region(hose->regions + 4, +        CFG_ISA_IO_BUS, +        CFG_ISA_IO_PHYS, +        CFG_ISA_IO_SIZE, +        PCI_REGION_IO); + +    hose->region_count = 5; + +    pci_setup_indirect(hose, +        MPC106_REG_ADDR, +        MPC106_REG_DATA); + +    pci_register_hose(hose); + +    hose->last_busno = pci_hose_scan(hose); + +    /* Initialises the MPC10x PCI Configuration regs. */ +    pci_read_config_word (PCI_BDF(0,0,0), PCI_COMMAND, ®16); +    reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; +    pci_write_config_word(PCI_BDF(0,0,0), PCI_COMMAND, reg16); + +    /* Clear non-reserved bits in status register */ +    pci_write_config_word(PCI_BDF(0,0,0), PCI_STATUS, 0xffff); +} + +#endif /* CONFIG_PCI */ diff --git a/board/eltec/elppc/srom.h b/board/eltec/elppc/srom.h new file mode 100644 index 000000000..7924bcd40 --- /dev/null +++ b/board/eltec/elppc/srom.h @@ -0,0 +1,102 @@ +/* + * (C) Copyright 2002 ELTEC Elektronik AG + * Frank Gottschling <fgottschling@eltec.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 + */ + +/* common srom defs */ +#define FIRST_DEVICE            0x00 +#define SECOND_DEVICE           0x04 +#define FIRST_BLOCK             0x00 +#define SECOND_BLOCK            0x02 +#define BLOCK_SIZE              0x100 +#define ERROR                   (-1) + +#define CLK2P0TO1_1MB_PB_0P5DH  0x79000100 +#define CLK2P5TO1_1MB_PB_0P5DH  0x7B000100 + +#define CPU_TYPE_740            0x08 +#define CPU_TYPE_750            0x08 +#define CPU_TYPE                ((get_pvr()>>16)&0xffff) + +#define ABS(x)                  ((x<0)?-x:x) +#define SROM_SHORT(pX)          (*(u8 *)(pX) | *((u8 *)(pX)+1) << 8) + +/* bab7xx ELTEC srom */ +#define I2C_BUS_DAT             (CFG_ISA_IO + 0x220) +#define I2C_BUS_DIR             (CFG_ISA_IO + 0x221) + +/* srom at mpc107 */ +#define MPC107_I2CADDR          (mpc107_eumb_addr + 0x3000)     /* address      */ +#define MPC107_I2CFDR           (mpc107_eumb_addr + 0x3004)     /* freq divider */ +#define MPC107_I2CCR            (mpc107_eumb_addr + 0x3008)     /* control      */ +#define MPC107_I2CSR            (mpc107_eumb_addr + 0x300c)     /* status       */ +#define MPC107_I2CDR            (mpc107_eumb_addr + 0x3010)     /* data         */ +#define MPC107_I2C_TIMEOUT      10000000 + +/* i82559 */ +#define EE_ADDR_BITS            6 +#define EE_SIZE                 0x40                            /* 0x40 words */ +#define EE_CHECKSUM             0xBABA + +/* dc21143 */ +#define DEC_SROM_SIZE           128 + + +/* + * structure of revision srom + */ +typedef struct  { +    char    magic[8];           /* 000 - Magic number */ +    char    revrev[2];          /* 008 - Revision of structure */ +    unsigned short size;        /* 00A - Size of CRC area */ +    unsigned long  crc;         /* 00C - CRC */ +    char    board[16];          /* 010 - Board Revision information */ +    char    option[4][16];      /* 020 - Option Revision information */ +    char    serial[8];          /* 060 - Board serial number */ +    char    etheraddr[6];       /* 068 - Ethernet node addresse */ +    char    reserved[2];        /* 06E - Reserved */ +    char    revision[7][2];     /* 070 - Revision codes */ +    char    category[2];        /* 07E - Category codes */ +    char    text[64];           /* 080 - Text field */ +    char    res[64];            /* 0C0 - Reserved */ +} revinfo; + +unsigned long el_srom_checksum (unsigned char *ptr, unsigned long size); +int el_srom_load  (unsigned char addr, unsigned char *buf, int cnt, +                   unsigned char device, unsigned char block); +int el_srom_store (unsigned char addr, unsigned char *buf, int cnt, +                   unsigned char device, unsigned char block); + +int mpc107_i2c_init (unsigned long eumb_addr, unsigned long divider); +int mpc107_i2c_read_byte (unsigned char device, unsigned char block, unsigned char offset); +int mpc107_i2c_write_byte (unsigned char device, unsigned char block, +                           unsigned char offset, unsigned char val); +int mpc107_srom_load (unsigned char addr, unsigned char *pBuf, int cnt, +                      unsigned char device, unsigned char block); +int mpc107_srom_store (unsigned char addr, unsigned char *pBuf, int cnt, +                       unsigned char device, unsigned char block); + +int dc_srom_load (unsigned short *dest); +int dc_srom_store (unsigned short *src); + +unsigned short eepro100_srom_checksum (unsigned short *sromdata); +void eepro100_srom_load (unsigned short *destination); +int  eepro100_srom_store (unsigned short *source); |