diff options
Diffstat (limited to 'board/eltec/bab7xx/dc_srom.c')
-rw-r--r-- | board/eltec/bab7xx/dc_srom.c | 291 |
1 files changed, 291 insertions, 0 deletions
diff --git a/board/eltec/bab7xx/dc_srom.c b/board/eltec/bab7xx/dc_srom.c new file mode 100644 index 0000000..ef956e6 --- /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); +} + +/*----------------------------------------------------------------------------*/ |