From: wdenk Date: Thu, 8 Aug 2002 07:41:42 +0000 (+0000) Subject: Patch by Wolfgang Grandegger, 07 Aug 2002: X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=ae5869e2dd42f4dd1dd16b38f373e596fb141488;p=users%2Frw%2Fppcboot.git Patch by Wolfgang Grandegger, 07 Aug 2002: - Support for PN62 boards added. - Boards without FLASH are now supported (CFG_NO_FLASH and CFG_ENV_IS_NOWHERE added). - Network driver for AMD PCnet/FAST III 79C973 (CONFIG_PCNET and CONFIG_PCNET_79C973) added. - Enhanced "pci" command implemented (allowing PCI conf. accesses). - The "mm" command now accepts the "-" key stroke to go back to the previous address. --- diff --git a/CHANGELOG b/CHANGELOG index b606f3d..6e20139 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,16 @@ Modifications for 1.2.0: ====================================================================== +* Patch by Wolfgang Grandegger, 07 Aug 2002: + - Support for PN62 boards added. + - Boards without FLASH are now supported (CFG_NO_FLASH and + CFG_ENV_IS_NOWHERE added). + - Network driver for AMD PCnet/FAST III 79C973 (CONFIG_PCNET and + CONFIG_PCNET_79C973) added. + - Enhanced "pci" command implemented (allowing PCI conf. accesses). + - The "mm" command now accepts the "-" key stroke to go back to the + previous address. + * Patch by Greg Allen, 6 Aug 2002: Support for UTX8245 Board diff --git a/Makefile b/Makefile index e6d5cf5..b58c96c 100644 --- a/Makefile +++ b/Makefile @@ -434,6 +434,9 @@ MUSENKI_config: unconfig OXC_config: unconfig @./mkconfig $(@:_config=) ppc mpc824x oxc +PN62_config: unconfig + @./mkconfig $(@:_config=) ppc mpc824x pn62 + Sandpoint8240_config: unconfig @./mkconfig $(@:_config=) ppc mpc824x sandpoint @@ -530,7 +533,6 @@ TQM8260_300MHz_config: unconfig } @./mkconfig -a $(call xtract_82xx,$@) ppc mpc8260 tqm8260 - ######################################################################### ## 74xx/7xx Systems ######################################################################### diff --git a/board/pn62/Makefile b/board/pn62/Makefile new file mode 100644 index 0000000..77e216b --- /dev/null +++ b/board/pn62/Makefile @@ -0,0 +1,40 @@ +# +# (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 cmd_pn62.o misc.o + +$(LIB): .depend $(OBJS) + $(AR) crv $@ $^ + +######################################################################### + +.depend: Makefile $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/board/pn62/cmd_pn62.c b/board/pn62/cmd_pn62.c new file mode 100644 index 0000000..dbe777c --- /dev/null +++ b/board/pn62/cmd_pn62.c @@ -0,0 +1,164 @@ +/* + * (C) Copyright 2002 + * Wolfgang Grandegger, DENX Software Engineering, wg@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "pn62.h" + +#if (CONFIG_COMMANDS & CFG_CMD_BSP) + +extern int do_bootm (cmd_tbl_t *, bd_t *, int, int, char *[]); + +/* + * Command led: controls the various LEDs 0..11 on the PN62 card. + */ +int do_led (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) +{ + unsigned int number, function; + + if (argc != 3) { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + number = simple_strtoul(argv[1], NULL, 10); + if (number > PN62_LED_MAX) + return 1; + function = simple_strtoul(argv[2], NULL, 16); + set_led (number, function); + return 0; +} + +/* + * Command loadpci: loads a image over PCI. + */ +#define CMD_MOVE_WINDOW 0x1 +#define CMD_BOOT_IMAGE 0x2 + +int do_loadpci (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) +{ + char *s; + ulong addr = 0, count = 0; + u32 off; + int cmd, rcode = 0; + + /* pre-set load_addr */ + if ((s = getenv("loadaddr")) != NULL) { + addr = simple_strtoul(s, NULL, 16); + } + + switch (argc) { + case 1: + break; + case 2: + addr = simple_strtoul(argv[1], NULL, 16); + break; + default: + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + printf ("## Ready for image download ...\n"); + + show_startup_phase(12); + + while (1) { + /* Alive indicator */ + i2155x_write_scrapad(BOOT_PROTO, BOOT_PROTO_READY); + + /* Toggle status LEDs */ + cmd = (count / 200) % 4; /* downscale */ + set_led(4, cmd == 0 ? LED_1 : LED_0); + set_led(5, cmd == 1 ? LED_1 : LED_0); + set_led(6, cmd == 2 ? LED_1 : LED_0); + set_led(7, cmd == 3 ? LED_1 : LED_0); + udelay(1000); + count++; + + cmd = i2155x_read_scrapad(BOOT_CMD); + + if (cmd == BOOT_CMD_MOVE) { + off = i2155x_read_scrapad(BOOT_DATA); + off += addr; + i2155x_set_bar_base(3, off); + printf ("## BAR3 Addr moved = 0x%08x\n", off); + i2155x_write_scrapad(BOOT_CMD, ~cmd); + show_startup_phase(13); + } + else if (cmd == BOOT_CMD_BOOT) { + set_led(4, LED_1); + set_led(5, LED_1); + set_led(6, LED_1); + set_led(7, LED_1); + + i2155x_write_scrapad(BOOT_CMD, ~cmd); + show_startup_phase(14); + break; + } + + /* Abort if ctrl-c was pressed */ + if (ctrlc()) { + printf("\nAbort\n"); + return 0; + } + + } + + /* Repoint to the default shared memory */ + i2155x_set_bar_base(3, PN62_SMEM_DEFAULT); + + load_addr = addr; + printf ("## Start Addr = 0x%08lx\n", addr); + + show_startup_phase(15); + + /* Loading ok, check if we should attempt an auto-start */ + if (((s = getenv("autostart")) != NULL) && (strcmp(s,"yes") == 0)) { + char *local_args[2]; + local_args[0] = argv[0]; + local_args[1] = NULL; + + printf ("Automatic boot of image at addr 0x%08lX ...\n", + load_addr); + rcode = do_bootm (cmdtp, bd, 0, 1, local_args); + } + +#ifdef CONFIG_AUTOSCRIPT + if (load_addr) { + char *s; + + if (((s = getenv("autoscript")) != NULL) && (strcmp(s,"yes") == 0)) { + printf("Running autoscript at addr 0x%08lX ...\n", load_addr); + rcode = autoscript (bd, load_addr); + } + } +#endif + return rcode; +} + +#endif diff --git a/board/pn62/config.mk b/board/pn62/config.mk new file mode 100644 index 0000000..a2b6f05 --- /dev/null +++ b/board/pn62/config.mk @@ -0,0 +1,30 @@ +# +# (C) Copyright 2000, 2001 +# 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 +# + +# +# PN62 boards +# + +TEXT_BASE = 0xFFF00000 + +PLATFORM_CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE) diff --git a/board/pn62/misc.c b/board/pn62/misc.c new file mode 100644 index 0000000..e86becc --- /dev/null +++ b/board/pn62/misc.c @@ -0,0 +1,235 @@ +/* + * (C) Copyright 2002 Wolfgang Grandegger + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "pn62.h" + +typedef struct { + pci_dev_t devno; + volatile u32 *csr; + +} i2155x_t; + +static i2155x_t i2155x = { 0, NULL }; + +static struct pci_device_id i2155x_ids[] = { + { 0x1011, 0x0046 }, /* i21554 */ + { 0x8086, 0xb555 } /* i21555 */ +}; + +int i2155x_init(void) +{ + pci_dev_t devno; + u32 val; + int i; + + /* + * Find the Intel bridge. + */ + if ((devno = pci_find_devices(i2155x_ids, 0)) < 0) { + printf("Error: Intel bridge 2155x not found!\n"); + return -1; + } + i2155x.devno = devno; + + /* + * Get auto-configured base address for CSR access. + */ + pci_read_config_dword(devno, PCI_BASE_ADDRESS_1, &val); + if (val & PCI_BASE_ADDRESS_SPACE_IO) { + val &= PCI_BASE_ADDRESS_IO_MASK; + i2155x.csr = (volatile u32 *)(_IO_BASE + val); + } else { + val &= PCI_BASE_ADDRESS_MEM_MASK; + i2155x.csr = (volatile u32 *)val; + } + + /* + * Translate downstream memory 2 (bar3) to base of shared memory. + */ + i2155x_set_bar_base(3, PN62_SMEM_DEFAULT); + + /* + * Enable memory space, I/O space and bus master bits + * in both Primary and Secondary command registers. + */ + val = PCI_COMMAND_MEMORY|PCI_COMMAND_MASTER|PCI_COMMAND_IO; + pci_write_config_word(devno, 0x44, val); + pci_write_config_word(devno, 0x04, val); + + /* + * Clear scratchpad registers. + */ + for (i = 0; i < (I2155X_SCRAPAD_MAX - 1); i++) { + i2155x_write_scrapad(i, 0x0); + } + + /* + * Set interrupt line for Linux. + */ + pci_write_config_byte(devno, PCI_INTERRUPT_LINE, 3); + + return 0; +} + +/* + * Access the Scratchpad registers 0..7 of the Intel bridge. + */ +void i2155x_write_scrapad(int idx, u32 val) +{ + if (idx >= 0 && idx < I2155X_SCRAPAD_MAX) + out_le32(i2155x.csr + (I2155X_SCRAPAD_ADDR/4) + idx, val); + else + printf("i2155x_write_scrapad: invalid index\n"); +} + +u32 i2155x_read_scrapad(int idx) +{ + if (idx >= 0 && idx < I2155X_SCRAPAD_MAX) + return in_le32(i2155x.csr + (I2155X_SCRAPAD_ADDR/4) + idx); + else + printf("i2155x_read_scrapad: invalid index\n"); + return -1; +} + +void i2155x_set_bar_base(int bar, u32 base) +{ + if (bar >= 2 && bar <= 4) { + pci_write_config_dword(i2155x.devno, + I2155X_BAR2_BASE + (bar - 2) * 4, + base); + } +} + +/* + * Read Vital Product Data (VPD) from the Serial EPROM attached + * to the Intel bridge. + */ +int i2155x_read_vpd(int offset, int size, unsigned char *data) +{ + int i, n; + u16 val16; + + for (i = 0; i < size; i++) { + pci_write_config_word(i2155x.devno, I2155X_VPD_ADDR, + offset + i - I2155X_VPD_START); + for (n = 10000; n > 0; n--) { + pci_read_config_word(i2155x.devno, I2155X_VPD_ADDR, &val16); + if ((val16 & 0x8000) != 0) /* wait for completion */ + break; + udelay(100); + } + if (n == 0) { + printf("i2155x_read_vpd: TIMEOUT\n"); + return -1; + } + + pci_read_config_byte(i2155x.devno, I2155X_VPD_DATA, &data[i]); + } + + return i; +} + +static struct pci_device_id am79c95x_ids [] = { + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE }, + { } +}; + + +/* + * Initialize the AMD ethernet controllers. + */ +int am79c95x_init(void) +{ + pci_dev_t devno; + int i; + + /* + * Set interrupt line for Linux. + */ + for (i = 0; i < 2; i++) { + if ((devno = pci_find_devices(am79c95x_ids, i)) < 0) + break; + pci_write_config_byte(devno, PCI_INTERRUPT_LINE, 2+i); + } + if (i < 2) + printf("Error: Only %d AMD Ethernet Controller found!\n", i); + + return 0; +} + + +void set_led(unsigned int number, unsigned int function) +{ + volatile u8 *addr; + + if ((number >= 0) && (number < PN62_LED_MAX) && + (function >= 0) && (function <= LED_LAST_FUNCTION)) { + addr = (volatile u8 *)(PN62_LED_BASE + number * 8); + out_8(addr, function&0xff); + } +} + +/* + * Show fatal error indicated by Kinght Rider(tm) effect + * in LEDS 0-7. LEDS 8-11 contain 4 bit error code. + * Note: this function will not terminate. + */ +void fatal_error(unsigned int error_code) +{ + int i, d; + + for (i = 0; i < 12; i++) { + set_led(i, LED_0); + } + + /* + * Write error code. + */ + set_led(8, (error_code & 0x01) ? LED_1 : LED_0); + set_led(9, (error_code & 0x02) ? LED_1 : LED_0); + set_led(10, (error_code & 0x04) ? LED_1 : LED_0); + set_led(11, (error_code & 0x08) ? LED_1 : LED_0); + + /* + * Yay - Knight Rider effect! + */ + while(1) { + unsigned int delay = 2000; + + for (i = 0; i < 8; i++) { + set_led(i, LED_1); + for (d = 0; d < delay; d++); + set_led(i, LED_0); + } + + for (i = 7; i > 0; i--) { + set_led(i, LED_1); + for (d = 0; d < delay; d++); + set_led(i, LED_0); + } + } +} diff --git a/board/pn62/pn62.c b/board/pn62/pn62.c new file mode 100644 index 0000000..e627dfd --- /dev/null +++ b/board/pn62/pn62.c @@ -0,0 +1,209 @@ +/* + * (C) Copyright 2002 Wolfgang Grandegger + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include + +#include "pn62.h" + + +static int get_serial_number(char *string, int size); +static int get_mac_address(int id, u8* mac, char *string, int size); + +#ifdef CONFIG_SHOW_BOOT_PROGRESS +void show_boot_progress(int phase) +{ + /* + * Show phases of the bootm command on the front panel + * LEDs and the scratchpad register #3 as well. We use + * blinking LEDs for logical "1". + */ + if (phase > 0) { + set_led( 8, (phase & 0x1) ? LED_SLOW_CLOCK : LED_0); + set_led( 9, (phase & 0x2) ? LED_SLOW_CLOCK : LED_0); + set_led(10, (phase & 0x4) ? LED_SLOW_CLOCK : LED_0); + set_led(11, (phase & 0x8) ? LED_SLOW_CLOCK : LED_0); + } + i2155x_write_scrapad(BOOT_STATUS, phase); + if (phase < 0) + i2155x_write_scrapad(BOOT_DONE, BOOT_DONE_ERROR); +} +#endif + +void show_startup_phase(int phase) { + /* + * Show the phase of PPCboot startup on the front panel + * LEDs and the scratchpad register #3 as well. + */ + if (phase > 0) { + set_led( 8, (phase & 0x1) ? LED_1 : LED_0); + set_led( 9, (phase & 0x2) ? LED_1 : LED_0); + set_led(10, (phase & 0x4) ? LED_1 : LED_0); + set_led(11, (phase & 0x8) ? LED_1 : LED_0); + } + i2155x_write_scrapad(BOOT_STATUS, phase); + if (phase < 0) + i2155x_write_scrapad(BOOT_DONE, BOOT_DONE_ERROR); +} + +int checkboard (void) +{ + show_startup_phase(1); + puts ( "PN62\n" ); + return 0; +} + +long int initdram (int board_type) +{ + int i, cnt; + volatile uchar * base= CFG_SDRAM_BASE; + volatile ulong * addr; + ulong save[32]; + ulong val, ret = 0; + + show_startup_phase(2); + + for (i=0, cnt=(CFG_MAX_RAM_SIZE / sizeof(long)) >> 1; cnt > 0; cnt >>= 1) { + addr = (volatile ulong *)base + cnt; + save[i++] = *addr; + *addr = ~cnt; + } + + addr = (volatile ulong *)base; + save[i] = *addr; + *addr = 0; + + if (*addr != 0) { + *addr = save[i]; + goto Done; + } + + for (cnt = 1; cnt <= CFG_MAX_RAM_SIZE / sizeof(long); cnt <<= 1) { + addr = (volatile ulong *)base + cnt; + val = *addr; + *addr = save[--i]; + if (val != ~cnt) { + ulong new_bank0_end = cnt * sizeof(long) - 1; + ulong mear1 = mpc824x_mpc107_getreg(MEAR1); + ulong emear1 = mpc824x_mpc107_getreg(EMEAR1); + mear1 = (mear1 & 0xFFFFFF00) | + ((new_bank0_end & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT); + emear1 = (emear1 & 0xFFFFFF00) | + ((new_bank0_end & MICR_ADDR_MASK) >> MICR_EADDR_SHIFT); + mpc824x_mpc107_setreg(MEAR1, mear1); + mpc824x_mpc107_setreg(EMEAR1, emear1); + + ret = cnt * sizeof(long); + goto Done; + } + } + + ret = CFG_MAX_RAM_SIZE; + Done: + show_startup_phase(3); + return ret; +} + +/* + * Initialize PCI Devices. We rely on auto-configuration. + */ +#ifndef CONFIG_PCI_PNP +#error "CONFIG_PCI_PNP is not defined, please correct!" +#endif + +struct pci_controller hose = { +}; + +void pci_init (bd_t *bd) +{ + show_startup_phase(4); + pci_mpc824x_init(bd, &hose); + + show_startup_phase(5); + i2155x_init(); + show_startup_phase(6); + am79c95x_init(); + show_startup_phase(7); +} + +void misc_init_r (bd_t *bd) +{ + char str[20]; + u8 mac[6]; + + show_startup_phase(8); + /* + * Get serial number and ethernet addresses if not already defined + * and update the board info structure and the environment. + */ + if (getenv("serial#") == NULL && + get_serial_number(str, strlen(str)) > 0) { + setenv("serial#", str); + } + show_startup_phase(9); + + if (getenv("ethaddr") == NULL && + get_mac_address(0, mac, str, sizeof(str)) > 0) { + setenv("ethaddr", str); + memcpy(bd->bi_enetaddr, mac, 6); + } + show_startup_phase(10); + + if (getenv("eth1addr") == NULL && + get_mac_address(1, mac, str, sizeof(str)) > 0) { + setenv("eth1addr", str); + memcpy(bd->bi_enet1addr, mac, 6); + } + show_startup_phase(11); + + /* Tell everybody that PPCboot is up and runnig */ + i2155x_write_scrapad(0, 0x12345678); +} + +static int get_serial_number (char* string, int size) +{ + int i; + char c; + + if (size < I2155X_VPD_SN_SIZE) + size = I2155X_VPD_SN_SIZE; + for (i = 0; i < (size - 1); i++) { + i2155x_read_vpd(I2155X_VPD_SN_START + i, 1, &c); + if (c == '\0') + break; + string[i] = c; + } + string[i] = '\0'; /* make sure it's terminated */ + + return i; +} + +static int get_mac_address (int id, u8* mac, char* string, int size) +{ + if (size < 6*3) + return -1; + + i2155x_read_vpd(I2155X_VPD_MAC0_START + 6 * id, 6, mac); + return sprintf(string, "%02x:%02x:%02x:%02x:%02x:%02x", + mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]); +} diff --git a/board/pn62/pn62.h b/board/pn62/pn62.h new file mode 100644 index 0000000..7719453 --- /dev/null +++ b/board/pn62/pn62.h @@ -0,0 +1,161 @@ +/* + * (C) Copyright 2002 Wolfgang Grandegger + * + * 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 + */ + +#ifndef _PN62_H_ +#define _PN62_H_ + +/* + * Definitions for the Intel Bridge 21554 or 21555. + */ +#define I2155X_VPD_ADDR 0xe6 +#define I2155X_VPD_DATA 0xe8 + +#define I2155X_VPD_START 0x80 +#define I2155X_VPD_SN_START 0x80 +#define I2155X_VPD_SN_SIZE 0x10 +#define I2155X_VPD_MAC0_START 0x90 +#define I2155X_VPD_MAC1_START 0x96 + +#define I2155X_SCRAPAD_ADDR 0xa8 +#define I2155X_SCRAPAD_MAX 8 + +#define I2155X_BAR2_BASE 0x98 +#define I2155X_BAR3_BASE 0x9c +#define I2155X_BAR4_BASE 0xa0 + +#define I2155X_BAR2_SETUP 0xb0 +#define I2155X_BAR3_SETUP 0xb4 +#define I2155X_BAR4_SETUP 0xb8 + +/* + * Interrupt request numbers + */ +#define PN62_IRQ_HOST 0x0 +#define PN62_IRQ_PLX9054 0x1 +#define PN62_IRQ_ETH0 0x2 +#define PN62_IRQ_ETH1 0x3 +#define PN62_IRQ_COM1 0x4 +#define PN62_IRQ_COM2 0x4 + +/* + * Miscellaneous definitons. + */ +#define PN62_SMEM_DEFAULT 0x1f00000 + +/* + * Definitions for boot protocol using Scratchpad registers. + */ +#define BOOT_DONE 0 +#define BOOT_DONE_CLEAR 0x00dead00 +#define BOOT_DONE_ERROR 0xbad0dead +#define BOOT_DONE_PPCBOOT 0x12345678 +#define BOOT_DONE_LINUX 0x87654321 +#define BOOT_CMD 1 +#define BOOT_CMD_MOVE 0x1 +#define BOOT_CMD_BOOT 0x2 +#define BOOT_DATA 2 +#define BOOT_PROTO 3 +#define BOOT_PROTO_READY 0x23456789 +#define BOOT_PROTO_CLEAR 0x00000000 +#define BOOT_STATUS 4 + +/* + * LED Definitions: + */ +#define PN62_LED_BASE 0xff800300 +#define PN62_LED_MAX 12 + +/* + * LED0 - 7 mounted on top of board, D1 - D8 + * LED8 - 11 upper four LEDs on the front panel of the board. + */ +#define LED_0 0x00 /* OFF */ +#define LED_1 0x01 /* ON */ +#define LED_SLOW_CLOCK 0x02 /* SLOW 1Hz ish */ +#define LED_nSLOW_CLOCK 0x03 /* inverse of above */ +#define LED_WATCHDOG_OUT 0x06 /* Reset Watchdog level */ +#define LED_WATCHDOG_CLOCK 0x07 /* clock to watchdog */ + +/* + * LED's currently setup in AMD79C973 device as the following: + * LED0 100Mbit + * LED1 LNKSE + * LED2 TX Activity + * LED3 RX Activity + */ +#define LED_E0_LED0 0x08 /* Ethernet Port 0 LED 0 */ +#define LED_E0_LED1 0x09 /* Ethernet Port 0 LED 1 */ +#define LED_E0_LED2 0x0A /* Ethernet Port 0 LED 2 */ +#define LED_E0_LED3 0x0B /* Ethernet Port 0 LED 3 */ +#define LED_E1_LED0 0x0C /* Ethernet Port 1 LED 0 */ +#define LED_E1_LED1 0x0D /* Ethernet Port 1 LED 1 */ +#define LED_E1_LED2 0x0E /* Ethernet Port 1 LED 2 */ +#define LED_E1_LED3 0x0F /* Ethernet Port 1 LED 3 */ +#define LED_STROBE0 0x10 /* Processor Strobe 0 */ +#define LED_STROBE1 0x11 /* Processor Strobe 1 */ +#define LED_STROBE2 0x12 /* Processor Strobe 2 */ +#define LED_STROBE3 0x13 /* Processor Strobe 3 */ +#define LED_STROBE4 0x14 /* Processor Strobe 4 */ +#define LED_STROBE5 0x15 /* Processor Strobe 5 */ +#define LED_STROBE6 0x16 /* Processor Strobe 6 */ +#define LED_STROBE7 0x17 /* Processor Strobe 7 */ +#define LED_HOST_STROBE0 0x18 /* Host strobe 0 */ +#define LED_HOST_STROBE1 0x19 /* Host strobe 1 */ +#define LED_HOST_STROBE2 0x1A /* Host strobe 2 */ +#define LED_HOST_STROBE3 0x1B /* Host strobe 3 */ +#define LED_HOST_STROBE4 0x1C /* Host strobe 4 */ +#define LED_HOST_STROBE5 0x1D /* Host strobe 5 */ +#define LED_HOST_STROBE6 0x1E /* Host strobe 6 */ +#define LED_HOST_STROBE7 0x1F /* Host strobe 7 */ +#define LED_MPC_INT0 0x20 /* MPC8240 INT 0 */ +#define LED_MPC_INT1 0x21 /* MPC8240 INT 1 */ +#define LED_MPC_INT2 0x22 /* MPC8240 INT 2 */ +#define LED_MPC_INT3 0x23 /* MPC8240 INT 3 */ +#define LED_MPC_INT4 0x24 /* MPC8240 INT 4 */ +#define LED_UART0_CS 0x25 /* UART 0 Chip Select */ +#define LED_UART1_CS 0x26 /* UART 1 Chip Select */ +#define LED_SRAM_CS 0x27 /* SRAM Chip Select */ +#define LED_SRAM_WR 0x28 /* SRAM WR Signal */ +#define LED_SRAM_RD 0x29 /* SRAM RD Signal */ +#define LED_MPC_RCS0 0x2A /* MPC8240 RCS0 Signal */ +#define LED_S_PCI_FRAME 0x2B /* Secondary PCI Frame Signal */ +#define LED_MPC_CS0 0x2C /* MPC8240 CS0 Signal */ +#define LED_HOST_INT 0x2D /* MPC8240 to Host Interrupt signal */ +#define LED_LAST_FUNCTION LED_HOST_INT /* last function */ + +/* + * Forward declarations + */ +int i2155x_init (void); +void i2155x_write_scrapad(int idx, u32 val); +u32 i2155x_read_scrapad (int idx); +void i2155x_set_bar_base (int bar, u32 addr); +int i2155x_read_vpd (int offset, int size, unsigned char *data); + +int am79c95x_init (void); + +void set_led (unsigned int number, unsigned int function); +void fatal_error (unsigned int error_code); +void show_startup_phase (int phase); + + +#endif /* _PN62_H_ */ diff --git a/board/pn62/ppcboot.lds b/board/pn62/ppcboot.lds new file mode 100644 index 0000000..3c0dab9 --- /dev/null +++ b/board/pn62/ppcboot.lds @@ -0,0 +1,128 @@ +/* + * (C) Copyright 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +OUTPUT_ARCH(powerpc) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); +/* Do we need any of these for elf? + __DYNAMIC = 0; */ +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = + SIZEOF_HEADERS; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rel.text : { *(.rel.text) } + .rela.text : { *(.rela.text) } + .rel.data : { *(.rel.data) } + .rela.data : { *(.rela.data) } + .rel.rodata : { *(.rel.rodata) } + .rela.rodata : { *(.rela.rodata) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : { *(.init) } + .plt : { *(.plt) } + .text : + { + cpu/mpc824x/start.o (.text) + common/board.o (.text) + lib_ppc/ppcstring.o (.text) + lib_generic/vsprintf.o (.text) + lib_generic/crc32.o (.text) + lib_generic/zlib.o (.text) + + . = DEFINED(env_offset) ? env_offset : .; + common/environment.o (.text) + + *(.text) + + *(.fixup) + *(.got1) + . = ALIGN(16); + *(.rodata) + *(.rodata1) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + + /* Read-write section, merged into data segment: */ + . = (. + 0x0FFF) & 0xFFFFF000; + _erotext = .; + PROVIDE (erotext = .); + .reloc : + { + *(.got) + _GOT2_TABLE_ = .; + *(.got2) + _FIXUP_TABLE_ = .; + *(.fixup) + } + __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2; + __fixup_entries = (. - _FIXUP_TABLE_) >> 2; + + .data : + { + *(.data) + *(.data1) + *(.sdata) + *(.sdata2) + *(.dynamic) + CONSTRUCTORS + } + _edata = .; + PROVIDE (edata = .); + + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + . = ALIGN(4096); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(4096); + __init_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + + _end = . ; + PROVIDE (end = .); +} + diff --git a/common/board.c b/common/board.c index ed5457d..43419f6 100644 --- a/common/board.c +++ b/common/board.c @@ -484,8 +484,8 @@ board_init_f (ulong bootflag) load_sernum_ethaddr(bd); #endif -#ifdef CFG_GT_6426x - /* handle the 2nd and 3rd ethernet addresses */ +#if defined(CFG_GT_6426x) || defined(CONFIG_PN62) + /* handle the 2nd ethernet address */ i = getenv_r ("eth1addr", tmp, sizeof(tmp)); s = (i > 0) ? tmp : NULL; @@ -495,6 +495,9 @@ board_init_f (ulong bootflag) if (s) s = (*e) ? e+1 : e; } +#endif +#if defined(CFG_GT_6426x) + /* handle the 3rd ethernet address */ i = getenv_r ("eth2addr", tmp, sizeof(tmp)); s = (i > 0) ? tmp : NULL; @@ -554,7 +557,9 @@ void board_init_r (bd_t *bd, ulong dest_addr) { char *s; cmd_tbl_t *cmdtp; +#ifndef CFG_NO_FLASH ulong flash_size; +#endif ulong reloc_off = dest_addr - CFG_MONITOR_BASE; extern void malloc_bin_reloc (ulong); @@ -623,6 +628,7 @@ void board_init_r (bd_t *bd, ulong dest_addr) */ trap_init(dest_addr); +#if !defined(CFG_NO_FLASH) puts ("FLASH: "); if ((flash_size = flash_init ()) > 0) { @@ -667,6 +673,12 @@ void board_init_r (bd_t *bd, ulong dest_addr) #else bd->bi_flashoffset = 0; #endif +#else + + bd->bi_flashsize = 0; + bd->bi_flashstart = 0; + bd->bi_flashoffset = 0; +#endif /* !CFG_NO_FLASH */ WATCHDOG_RESET(); diff --git a/common/cmd_boot.c b/common/cmd_boot.c index 75ac09b..a646b52 100644 --- a/common/cmd_boot.c +++ b/common/cmd_boot.c @@ -85,6 +85,12 @@ int do_bdinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) for (i=0; i<6; ++i) { printf ("%c%02X", i ? ':' : ' ', bd->bi_enetaddr[i]); } +#ifdef CONFIG_PN62 + printf ("\neth1addr ="); + for (i=0; i<6; ++i) { + printf ("%c%02X", i ? ':' : ' ', bd->bi_enet1addr[i]); + } +#endif /* CONFIG_PN62 */ #ifdef CONFIG_HERMES print_str ("ethspeed", strmhz(buf, bd->bi_ethspeed)); #endif diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 36565ce..ac9ba63 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -128,7 +128,7 @@ int do_bootm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) if (crc32 (0, (char *)data, len) != checksum) { printf ("Bad Header Checksum\n"); - SHOW_BOOT_PROGRESS (-1); + SHOW_BOOT_PROGRESS (-2); return 1; } SHOW_BOOT_PROGRESS (3); @@ -143,7 +143,7 @@ int do_bootm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) printf (" Verifying Checksum ... "); if (crc32 (0, (char *)data, len) != hdr->ih_dcrc) { printf ("Bad Data CRC\n"); - SHOW_BOOT_PROGRESS (-1); + SHOW_BOOT_PROGRESS (-3); return 1; } printf ("OK\n"); @@ -154,7 +154,7 @@ int do_bootm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) if (hdr->ih_arch != IH_CPU_PPC) { printf ("Unsupported Architecture\n"); - SHOW_BOOT_PROGRESS (-1); + SHOW_BOOT_PROGRESS (-4); return 1; } SHOW_BOOT_PROGRESS (5); @@ -172,8 +172,8 @@ int do_bootm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) data += 4; break; default: printf ("Wrong Image Type for %s command\n", cmdtp->name); - SHOW_BOOT_PROGRESS (-1); - return 1; + SHOW_BOOT_PROGRESS (-5); + return 1; } SHOW_BOOT_PROGRESS (6); @@ -199,6 +199,7 @@ int do_bootm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) if (gunzip ((void *)hdr->ih_load, 0x400000, (uchar *)data, (int *)&len) != 0) { printf ("GUNZIP ERROR - must RESET board to recover\n"); + SHOW_BOOT_PROGRESS (-6); do_reset (cmdtp, bd, flag, argc, argv); } break; @@ -206,7 +207,7 @@ int do_bootm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) if (iflag) enable_interrupts(); printf ("Unimplemented compression type %d\n", hdr->ih_comp); - SHOW_BOOT_PROGRESS (-1); + SHOW_BOOT_PROGRESS (-7); return 1; } printf ("OK\n"); @@ -228,7 +229,7 @@ int do_bootm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) if (iflag) enable_interrupts(); printf ("Can't boot image type %d\n", hdr->ih_type); - SHOW_BOOT_PROGRESS (-1); + SHOW_BOOT_PROGRESS (-8); return 1; } SHOW_BOOT_PROGRESS (8); @@ -255,7 +256,7 @@ int do_bootm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) #endif /* CFG_CMD_ELF */ } - SHOW_BOOT_PROGRESS (-1); + SHOW_BOOT_PROGRESS (-9); #ifdef DEBUG printf ("\n## Control returned to monitor - resetting...\n"); do_reset (cmdtp, bd, flag, argc, argv); @@ -362,7 +363,7 @@ do_bootm_linux (cmd_tbl_t *cmdtp, bd_t *bd, int flag, if (hdr->ih_magic != IH_MAGIC) { printf ("Bad Magic Number\n"); - SHOW_BOOT_PROGRESS (-1); + SHOW_BOOT_PROGRESS (-10); do_reset (cmdtp, bd, flag, argc, argv); } @@ -374,7 +375,7 @@ do_bootm_linux (cmd_tbl_t *cmdtp, bd_t *bd, int flag, if (crc32 (0, (char *)data, len) != checksum) { printf ("Bad Header Checksum\n"); - SHOW_BOOT_PROGRESS (-1); + SHOW_BOOT_PROGRESS (-11); do_reset (cmdtp, bd, flag, argc, argv); } @@ -412,7 +413,7 @@ do_bootm_linux (cmd_tbl_t *cmdtp, bd_t *bd, int flag, if (csum != hdr->ih_dcrc) { printf ("Bad Data CRC\n"); - SHOW_BOOT_PROGRESS (-1); + SHOW_BOOT_PROGRESS (-12); do_reset (cmdtp, bd, flag, argc, argv); } printf ("OK\n"); @@ -424,7 +425,7 @@ do_bootm_linux (cmd_tbl_t *cmdtp, bd_t *bd, int flag, (hdr->ih_arch != IH_CPU_PPC) || (hdr->ih_type != IH_TYPE_RAMDISK) ) { printf ("No Linux PPC Ramdisk Image\n"); - SHOW_BOOT_PROGRESS (-1); + SHOW_BOOT_PROGRESS (-13); do_reset (cmdtp, bd, flag, argc, argv); } diff --git a/common/cmd_i2c.c b/common/cmd_i2c.c index eda00fc..98ff3c9 100644 --- a/common/cmd_i2c.c +++ b/common/cmd_i2c.c @@ -88,6 +88,7 @@ #if (CONFIG_COMMANDS & CFG_CMD_I2C) + /* Display values from last command. * Memory modify remembered values are different from display memory. */ @@ -102,6 +103,7 @@ static uint i2c_mm_last_alen; static int mod_i2c_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char *argv[]); +extern int cmd_get_data_size(char* arg, int default_size); /* * Syntax: @@ -417,16 +419,7 @@ mod_i2c_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char *argv[]) * New command specified. Check for a size specification. * Defaults to byte if no or incorrect specification. */ - size = 1; - if (argv[0][3] == '.') { - if (argv[0][4] == 'b') { - size = 1; - } else if (argv[0][4] == 'w') { - size = 2; - } else if (argv[0][4] == 'l') { - size = 4; - } - } + size = cmd_get_data_size(argv[0], 1); /* * Chip is always specified. diff --git a/common/cmd_mem.c b/common/cmd_mem.c index 63162b0..3eaa629 100644 --- a/common/cmd_mem.c +++ b/common/cmd_mem.c @@ -31,6 +31,26 @@ #include #include +#if (CONFIG_COMMANDS & (CFG_CMD_MEMORY | CFG_CMD_PCI | CFG_CMD_I2C)) +int cmd_get_data_size(char* arg, int default_size) +{ + /* Check for a size specification .b, .w or .l. + */ + int len = strlen(arg); + if (len > 2 && arg[len-2] == '.') { + switch(arg[len-1]) { + case 'b': + return 1; + case 'w': + return 2; + case 'l': + return 4; + } + } + return default_size; +} +#endif + #if (CONFIG_COMMANDS & CFG_CMD_MEMORY) static int mod_mem(cmd_tbl_t *, int, int, int, char *[]); @@ -72,14 +92,7 @@ int do_mem_md (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) /* New command specified. Check for a size specification. * Defaults to long if no or incorrect specification. */ - size = 4; - if (argv[0][2] == '.') { - if (argv[0][3] == 'b') { - size = 1; - } else if (argv[0][3] == 'w') { - size = 2; - } - } + size = cmd_get_data_size(argv[0], 4); /* Address is specified since argc > 1 */ @@ -160,14 +173,7 @@ int do_mem_mw (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) /* Check for size specification. */ - size = 4; - if (argv[0][2] == '.') { - if (argv[0][3] == 'b') { - size = 1; - } else if (argv[0][3] == 'w') { - size = 2; - } - } + size = cmd_get_data_size(argv[0], 4); /* Address is specified since argc > 1 */ @@ -209,14 +215,7 @@ int do_mem_cmp (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) /* Check for size specification. */ - size = 4; - if (argv[0][3] == '.') { - if (argv[0][4] == 'b') { - size = 1; - } else if (argv[0][4] == 'w') { - size = 2; - } - } + size = cmd_get_data_size(argv[0], 4); addr1 = simple_strtoul(argv[1], NULL, 16); addr1 += base_address; @@ -284,14 +283,7 @@ int do_mem_cp (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) /* Check for size specification. */ - size = 4; - if (argv[0][2] == '.') { - if (argv[0][3] == 'b') { - size = 1; - } else if (argv[0][3] == 'w') { - size = 2; - } - } + size = cmd_get_data_size(argv[0], 4); addr = simple_strtoul(argv[1], NULL, 16); addr += base_address; @@ -306,6 +298,7 @@ int do_mem_cp (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) return 1; } +#ifndef CFG_NO_FLASH /* check if we are copying to Flash */ if (addr2info(dest) != NULL) { int rc; @@ -329,6 +322,7 @@ int do_mem_cp (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) return 1; } } +#endif while (count-- > 0) { if (size == 4) @@ -371,13 +365,7 @@ int do_mem_loop (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) /* Check for a size spefication. * Defaults to long if no or incorrect specification. */ - size = 4; - if (argv[0][4] == '.') { - if (argv[0][5] == 'b') - size = 1; - else if (argv[0][5] == 'w') - size = 2; - } + size = cmd_get_data_size(argv[0], 4); /* Address is always specified. */ @@ -528,14 +516,7 @@ mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char *argv[]) /* New command specified. Check for a size specification. * Defaults to long if no or incorrect specification. */ - size = 4; - if (argv[0][2] == '.') { - if (argv[0][3] == 'b') { - size = 1; - } else if (argv[0][3] == 'w') { - size = 2; - } - } + size = cmd_get_data_size(argv[0], 4); /* Address is specified since argc > 1 */ @@ -556,12 +537,12 @@ mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char *argv[]) printf(" %02x", *((u_char *)addr)); nbytes = readline (" ? "); - if (nbytes == 0) { + if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) { /* pressed as only input, don't modify current - * location and move to next. + * location and move to next. "-" pressed will go back. */ if (incrflag) - addr += size; + addr += nbytes ? -size : size; nbytes = 1; #ifdef CONFIG_BOOT_RETRY_TIME reset_cmd_timeout(); /* good enough to not time out */ diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c index 2cdb89f..00d2b0c 100644 --- a/common/cmd_nvedit.c +++ b/common/cmd_nvedit.c @@ -152,8 +152,13 @@ static uchar *flash_addr = (uchar *)CFG_ENV_ADDR; # endif /* ENV, FLASH */ # endif /* ENV_IS_EMBEDDED */ + +/*--- NOWHERE ---------------------------------------------------------*/ +#elif defined(CFG_ENV_IS_NOWHERE) /* Environment is nowhere */ +static env_t *env_ptr = NULL; + #else -# error Define one of CFG_ENV_IS_IN_NVRAM, CFG_ENV_IS_IN_EEPROM, CFG_ENV_IS_IN_FLASH +# error Define one of CFG_ENV_IS_IN_NVRAM, CFG_ENV_IS_IN_EEPROM, CFG_ENV_IS_IN_FLASH, CFG_ENV_IS_NOWHERE #endif /* CFG_ENV_IS_IN_FLASH */ /*----------------------------------------------------------------------*/ @@ -299,7 +304,7 @@ void env_relocate (ulong offset) get_env_addr = get_env_addr_memory; if (idata->env_valid == 0) { -#if defined(CONFIG_GTH) /* Environment not changable */ +#if defined(CONFIG_GTH) || defined(CFG_ENV_IS_NOWHERE) /* Environment not changable */ puts ("Using default environment\n\n"); #else puts ("*** Warning - bad CRC, using default environment\n\n"); @@ -323,7 +328,7 @@ void env_relocate (ulong offset) eeprom_read (CFG_DEF_EEPROM_ADDR, CFG_ENV_OFFSET+offsetof(env_t,data), env_ptr->data, ENV_SIZE); -# else +# elif !defined(CFG_ENV_IS_NOWHERE) DEBUGF ("%s[%d] read ENV from NVRAM/FLASH\n",__FUNCTION__,__LINE__); memcpy (env_ptr->data, ((env_t *)CFG_ENV_ADDR)->data, diff --git a/common/cmd_pci.c b/common/cmd_pci.c index 2f204e8..cba59af 100644 --- a/common/cmd_pci.c +++ b/common/cmd_pci.c @@ -4,6 +4,7 @@ * * (C) Copyright 2002 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * Wolfgang Grandegger, DENX Software Engineering, wg@denx.de. * * See file CREDITS for list of people who contributed to this * project. @@ -41,44 +42,13 @@ #if (CONFIG_COMMANDS & CFG_CMD_PCI) -unsigned char ShortPCIListing = 0; +extern int cmd_get_data_size(char* arg, int default_size); -/* - * Follows routines for the output of infos about devices on PCI bus. - */ - -void pciinfo(int BusNum); +unsigned char ShortPCIListing = 1; /* - * Subroutine: do_pciinfo - * - * Description: Handler for 'pciinfo' command.. - * - * Inputs: argv[1] may contain the number of the bus to be scanned. - * Default is bus 0. - * - * Return: None - * + * Follows routines for the output of infos about devices on PCI bus. */ -int do_pciinfo(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) -{ - char *s; - int bus_no = 0; - - if (argc == 2) - { - bus_no = (int)simple_strtoul(argv[1], NULL, 10); - } - - if ((s = getenv("pci_listing")) != NULL) - ShortPCIListing = (strcmp(s, "short") == 0) ? 1 : 0; - else - ShortPCIListing = 0; - - pciinfo(bus_no); - - return 0; -} void pci_header_show(pci_dev_t dev); void pci_header_show_brief(pci_dev_t dev); @@ -90,12 +60,12 @@ void pci_header_show_brief(pci_dev_t dev); * Depending on the define CFG_SHORT_PCI_LISTING * the output will be more or less exhaustive. * - * Inputs: bus_no the number of the bus to be scanned. + * Inputs: bus_no the number of the bus to be scanned. * * Return: None * */ -void pciinfo(int BusNum) +void pciinfo(int BusNum, int ShortPCIListing) { int Device; int Function; @@ -106,8 +76,8 @@ void pciinfo(int BusNum) printf("Scanning PCI devices on bus %d\n", BusNum); if (ShortPCIListing) { - printf("No. VendorId DeviceId Device Class Sub-Class\n"); - printf("________________________________________________________\n"); + printf("BusDevFun VendorId DeviceId Device Class Sub-Class\n"); + printf("_____________________________________________________________\n"); } for (Device = 0; Device < PCI_MAX_PCI_DEVICES; Device++) { @@ -127,16 +97,16 @@ void pciinfo(int BusNum) continue; pci_read_config_byte(dev, PCI_HEADER_TYPE, &HeaderType); - + if (ShortPCIListing) { - printf("%02d.%d ", Device, Function); + printf("%02x.%02x.%02x ", BusNum, Device, Function); pci_header_show_brief(dev); } else { - printf("\nFound PCI device %d, function %d:\n", - Device, Function); + printf("\nFound PCI device %02x.%02x.%02x:\n", + BusNum, Device, Function); pci_header_show(dev); } } @@ -276,6 +246,232 @@ void pci_header_show(pci_dev_t dev) #undef PRINT2 } +/* Convert the "bus.device.function" identifier into a number. + */ +static pci_dev_t get_pci_dev(char* name) +{ + char cnum[12]; + int len, i, iold, n; + int bdfs[3] = {0,0,0}; + + len = strlen(name); + if (len > 8) + return -1; + for (i = 0, iold = 0, n = 0; i < len; i++) { + if (name[i] == '.') { + memcpy(cnum, &name[iold], i - iold); + cnum[i - iold] = '\0'; + bdfs[n++] = simple_strtoul(cnum, NULL, 16); + iold = i + 1; + } + } + strcpy(cnum, &name[iold]); + if (n == 0) + n = 1; + bdfs[n] = simple_strtoul(cnum, NULL, 16); + return PCI_BDF(bdfs[0], bdfs[1], bdfs[2]); +} + +static int pci_cfg_display(pci_dev_t bdf, ulong addr, ulong size, ulong length) +{ +#define DISP_LINE_LEN 16 + ulong i, nbytes, linebytes; + int rc = 0; + + if (length == 0) + length = 0x40 / size; /* Standard PCI configuration space */ + + /* Print the lines. + * once, and all accesses are with the specified bus width. + */ + nbytes = length * size; + do { + uint val4; + ushort val2; + u_char val1; + + printf("%08lx:", addr); + linebytes = (nbytes>DISP_LINE_LEN)?DISP_LINE_LEN:nbytes; + for (i=0; i 0); + + return (rc); +} + +static int pci_cfg_write (pci_dev_t bdf, ulong addr, ulong size, ulong value) +{ + if (size == 4) { + pci_write_config_dword(bdf, addr, value); + } + else if (size == 2) { + ushort val = value & 0xffff; + pci_write_config_word(bdf, addr, val); + } + else { + u_char val = value & 0xff; + pci_write_config_byte(bdf, addr, val); + } + return 0; +} + +static int +pci_cfg_modify (pci_dev_t bdf, ulong addr, ulong size, ulong value, int incrflag) +{ + ulong i; + int nbytes; + extern char console_buffer[]; + uint val4; + ushort val2; + u_char val1; + + /* Print the address, followed by value. Then accept input for + * the next value. A non-converted value exits. + */ + do { + printf("%08lx:", addr); + if (size == 4) { + pci_read_config_dword(bdf, addr, &val4); + printf(" %08x", val4); + } + else if (size == 2) { + pci_read_config_word(bdf, addr, &val2); + printf(" %04x", val2); + } + else { + pci_read_config_byte(bdf, addr, &val1); + printf(" %02x", val1); + } + + nbytes = readline (" ? "); + if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) { + /* pressed as only input, don't modify current + * location and move to next. "-" pressed will go back. + */ + if (incrflag) + addr += nbytes ? -size : size; + nbytes = 1; +#ifdef CONFIG_BOOT_RETRY_TIME + reset_cmd_timeout(); /* good enough to not time out */ +#endif + } +#ifdef CONFIG_BOOT_RETRY_TIME + else if (nbytes == -2) { + break; /* timed out, exit the command */ + } +#endif + else { + char *endp; + i = simple_strtoul(console_buffer, &endp, 16); + nbytes = endp - console_buffer; + if (nbytes) { +#ifdef CONFIG_BOOT_RETRY_TIME + /* good enough to not time out + */ + reset_cmd_timeout(); +#endif + pci_cfg_write (bdf, addr, size, i); + if (incrflag) + addr += size; + } + } + } while (nbytes); + + return 0; +} + +/* PCI Configuration Space access commands + * + * Syntax: + * pci display[.b, .w, .l] bus.device.function} [addr] [len] + * pci next[.b, .w, .l] bus.device.function [addr] + * pci modify[.b, .w, .l] bus.device.function [addr] + * pci write[.b, .w, .l] bus.device.function addr value + */ +int do_pci (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) +{ + ulong addr = 0, value = 0, size = 0; + pci_dev_t bdf = 0; + char cmd = 's'; + + if (argc > 1) + cmd = argv[1][0]; + + switch (cmd) { + case 'd': /* display */ + case 'n': /* next */ + case 'm': /* modify */ + case 'w': /* write */ + /* Check for a size specification. */ + size = cmd_get_data_size(argv[1], 4); + if (argc > 3) + addr = simple_strtoul(argv[3], NULL, 16); + if (argc > 4) + value = simple_strtoul(argv[4], NULL, 16); + case 'h': /* header */ + if (argc < 3) + goto usage; + if ((bdf = get_pci_dev(argv[2])) == -1) + return 1; + break; + default: /* scan bus */ + value = 1; /* short listing */ + bdf = 0; /* bus number */ + if (argc > 1) { + if (argv[argc-1][0] == 'l') { + value = 0; + argc--; + } + if (argc > 1) + bdf = simple_strtoul(argv[1], NULL, 16); + } + pciinfo(bdf, value); + return 0; + } + + switch (argv[1][0]) { + case 'h': /* header */ + pci_header_show(bdf); + return 0; + case 'd': /* display */ + return pci_cfg_display(bdf, addr, size, value); + case 'n': /* next */ + if (argc < 4) + goto usage; + return pci_cfg_modify(bdf, addr, size, value, 0); + case 'm': /* modify */ + if (argc < 4) + goto usage; + return pci_cfg_modify(bdf, addr, size, value, 1); + case 'w': /* write */ + if (argc < 5) + goto usage; + return pci_cfg_write(bdf, addr, size, value); + } + + return 1; + usage: + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; +} + #endif /* (CONFIG_COMMANDS & CFG_CMD_PCI) */ #endif /* CONFIG_PCI */ diff --git a/common/command.c b/common/command.c index 7d27cba..9b25d1f 100644 --- a/common/command.c +++ b/common/command.c @@ -282,7 +282,7 @@ cmd_tbl_t cmd_tbl[] = { CMD_TBL_MW CMD_TBL_NEXT CMD_TBL_NM - CMD_TBL_PCIINFO + CMD_TBL_PCI CMD_TBL_PRINTENV CMD_TBL_PROTECT CMD_TBL_RARPB diff --git a/common/flash.c b/common/flash.c index 0913d25..9565892 100644 --- a/common/flash.c +++ b/common/flash.c @@ -24,6 +24,8 @@ #include #include +#if !defined(CFG_NO_FLASH) + extern flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ /*----------------------------------------------------------------------- @@ -176,3 +178,5 @@ flash_write (uchar *src, ulong addr, ulong cnt) /*----------------------------------------------------------------------- */ + +#endif /* !CFG_NO_FLASH */ diff --git a/cpu/mpc824x/cpu_init.c b/cpu/mpc824x/cpu_init.c index 13fbf05..472bf60 100644 --- a/cpu/mpc824x/cpu_init.c +++ b/cpu/mpc824x/cpu_init.c @@ -68,7 +68,7 @@ cpu_init_f (void) CONFIG_WRITE_HALFWORD(PCICR, 0x06); /* Bus Master, respond to PCI memory space acesses*/ /* CONFIG_WRITE_HALFWORD(PCISR, 0xffff); */ /*reset PCISR*/ -#if defined(CONFIG_MUSENKI) +#if defined(CONFIG_MUSENKI) || defined(CONFIG_PN62) /* Why is this here, you ask? Try, just try setting 0x8000 * in PCIACR with CONFIG_WRITE_HALFWORD() * this one was a stumper, and we are annoyed @@ -124,7 +124,11 @@ cpu_init_f (void) CONFIG_READ_WORD(PICR2, val); val= val & ~ (PICR2_CF_SNOOP_WS_MASK | PICR2_CF_APHASE_WS_MASK); /*mask off waitstate bits*/ - CONFIG_WRITE_WORD(PICR2, val | PICR2_CF_SNOOP_WS_1WS | PICR2_CF_APHASE_WS_1WS); /*1 wait state*/ +#ifndef CONFIG_PN62 + val |= PICR2_CF_SNOOP_WS_1WS | PICR2_CF_APHASE_WS_1WS; /*1 wait state*/ +#endif + CONFIG_WRITE_WORD(PICR2, val); + CONFIG_WRITE_WORD(EUMBBAR, CFG_EUMB_ADDR); #ifndef CFG_RAMBOOT CONFIG_WRITE_WORD(MCCR1, (CFG_ROMNAL << MCCR1_ROMNAL_SHIFT) | @@ -164,7 +168,7 @@ cpu_init_f (void) * should define CFG_ACTORW to 0 if they don't want to set it, or even, if * its not set, we define it to zero in this file */ -#if defined(CONFIG_CU824) +#if defined(CONFIG_CU824) || defined(CONFIG_PN62) CONFIG_WRITE_WORD(MCCR4, (CFG_PRETOACT << MCCR4_PRETOACT_SHIFT) | (CFG_ACTTOPRE << MCCR4_ACTTOPRE_SHIFT) | diff --git a/drivers/Makefile b/drivers/Makefile index 40eebe6..7b72495 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -28,7 +28,7 @@ include $(TOPDIR)/config.mk LIB = libdrivers.a OBJS = ns87308.o ns16550.o serial.o pci_auto.o pci.o pci_indirect.o \ - eepro100.o dc2114x.o w83c553f.o sym53c8xx.o + eepro100.o dc2114x.o w83c553f.o sym53c8xx.o pcnet.o all: $(LIB) $(LIB): $(OBJS) diff --git a/drivers/pcnet.c b/drivers/pcnet.c new file mode 100644 index 0000000..7b80f0c --- /dev/null +++ b/drivers/pcnet.c @@ -0,0 +1,526 @@ +/* + * (C) Copyright 2002 Wolfgang Grandegger, wg@denx.de. + * + * This driver for AMD PCnet network controllers is derived from the + * Linux driver pcnet32.c written 1996-1999 by Thomas Bogendoerfer. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#if 0 +#define PCNET_DEBUG_LEVEL 0 /* 0=off, 1=init, 2=rx/tx */ +#endif + +#if PCNET_DEBUG_LEVEL > 0 +#define DEBUG1(fmt,args...) printf (fmt ,##args) +#if PCNET_DEBUG_LEVEL > 1 +#define DEBUG2(fmt,args...) printf (fmt ,##args) +#else +#define DEBUG2(fmt,args...) +#endif +#else +#define DEBUG1(fmt,args...) +#define DEBUG2(fmt,args...) +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) \ + && defined(CONFIG_PCNET) + +#if !defined(CONF_PCNET_79C973) && defined(CONF_PCNET_79C975) +#error "Macro for PCnet chip version is not defined!" +#endif + +/* + * Set the number of Tx and Rx buffers, using Log_2(# buffers). + * Reasonable default values are 4 Tx buffers, and 16 Rx buffers. + * That translates to 2 (4 == 2^^2) and 4 (16 == 2^^4). + */ +#define PCNET_LOG_TX_BUFFERS 0 +#define PCNET_LOG_RX_BUFFERS 2 + +#define TX_RING_SIZE (1 << (PCNET_LOG_TX_BUFFERS)) +#define TX_RING_LEN_BITS ((PCNET_LOG_TX_BUFFERS) << 12) + +#define RX_RING_SIZE (1 << (PCNET_LOG_RX_BUFFERS)) +#define RX_RING_LEN_BITS ((PCNET_LOG_RX_BUFFERS) << 4) + +#define PKT_BUF_SZ 1544 + +/* The PCNET Rx and Tx ring descriptors. */ +struct pcnet_rx_head { + u32 base; + s16 buf_length; + s16 status; + u32 msg_length; + u32 reserved; +}; + +struct pcnet_tx_head { + u32 base; + s16 length; + s16 status; + u32 misc; + u32 reserved; +}; + +/* The PCNET 32-Bit initialization block, described in databook. */ +struct pcnet_init_block { + u16 mode; + u16 tlen_rlen; + u8 phys_addr[6]; + u16 reserved; + u32 filter[2]; + /* Receive and transmit ring base, along with extra bits. */ + u32 rx_ring; + u32 tx_ring; + u32 reserved2; +}; + +typedef struct pcnet_priv { + struct pcnet_rx_head rx_ring[RX_RING_SIZE]; + struct pcnet_tx_head tx_ring[TX_RING_SIZE]; + struct pcnet_init_block init_block; + /* Receive Buffer space */ + unsigned char rx_buf[RX_RING_SIZE][PKT_BUF_SZ + 4]; + int cur_rx; + int cur_tx; +} pcnet_priv_t; + +static pcnet_priv_t *lp; + +/* Offsets from base I/O address for WIO mode */ +#define PCNET_RDP 0x10 +#define PCNET_RAP 0x12 +#define PCNET_RESET 0x14 +#define PCNET_BDP 0x16 + +static u16 pcnet_read_csr (struct eth_device *dev, int index) +{ + outw (index, dev->iobase+PCNET_RAP); + return inw (dev->iobase+PCNET_RDP); +} + +static void pcnet_write_csr (struct eth_device *dev, int index, u16 val) +{ + outw (index, dev->iobase+PCNET_RAP); + outw (val, dev->iobase+PCNET_RDP); +} + +static u16 pcnet_read_bcr (struct eth_device *dev, int index) +{ + outw (index, dev->iobase+PCNET_RAP); + return inw (dev->iobase+PCNET_BDP); +} + +static void pcnet_write_bcr (struct eth_device *dev, int index, u16 val) +{ + outw (index, dev->iobase+PCNET_RAP); + outw (val, dev->iobase+PCNET_BDP); +} + +static void pcnet_reset (struct eth_device *dev) +{ + inw (dev->iobase+PCNET_RESET); +} + +static int pcnet_check (struct eth_device *dev) +{ + outw (88, dev->iobase+PCNET_RAP); + return (inw (dev->iobase+PCNET_RAP) == 88); +} + +static int pcnet_init( struct eth_device* dev, bd_t *bis); +static int pcnet_send (struct eth_device* dev, volatile void *packet, + int length); +static int pcnet_recv (struct eth_device* dev); +static void pcnet_halt (struct eth_device* dev); +static int pcnet_probe(struct eth_device* dev, bd_t *bis, int dev_num); + +#define PCI_TO_MEM(d,a) pci_phys_to_mem((pci_dev_t)d->priv, (u_long)(a)) +#define PCI_TO_MEM_LE(d,a) (u32)(cpu_to_le32(PCI_TO_MEM(d,a))) + +static struct pci_device_id supported[] = { + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE }, + { } +}; + + +int pcnet_initialize(bd_t *bis) +{ + pci_dev_t devbusfn; + struct eth_device* dev; + u16 command, status; + int dev_nr = 0; + + DEBUG1("\npcnet_initialize...\n"); + + for (dev_nr = 0; ; dev_nr++) { + + /* + * Find the PCnet PCI device(s). + */ + if ((devbusfn = pci_find_devices(supported, dev_nr)) < 0) { + break; + } + + /* + * Allocate and pre-fill the device structure. + */ + dev = (struct eth_device*) malloc(sizeof *dev); + dev->priv = (void *)devbusfn; + sprintf(dev->name, "pcnet#%d", dev_nr); + + /* + * Setup the PCI device. + */ + pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, &dev->iobase); + dev->iobase &= ~0xf; + + DEBUG1("%s: devbusfn=0x%x iobase=0x%x: ", + dev->name, devbusfn, dev->iobase); + + command = PCI_COMMAND_IO | PCI_COMMAND_MASTER; + pci_write_config_word(devbusfn, PCI_COMMAND, command); + pci_read_config_word(devbusfn, PCI_COMMAND, &status); + if ((status & command) != command) { + printf("%s: Couldn't enable IO access or Bus Mastering\n", + dev->name); + free(dev); + continue; + } + + pci_write_config_byte(devbusfn, PCI_LATENCY_TIMER, 0x40); + + /* + * Probe the PCnet chip. + */ + if (pcnet_probe(dev, bis, dev_nr) < 0) { + free(dev); + continue; + } + + /* + * Setup device structure and register the driver. + */ + dev->init = pcnet_init; + dev->halt = pcnet_halt; + dev->send = pcnet_send; + dev->recv = pcnet_recv; + + eth_register(dev); + } + + udelay(10 * 1000); + + return dev_nr; +} + +static int pcnet_probe(struct eth_device* dev, bd_t *bis, int dev_nr) +{ + int chip_version; + char *chipname; +#ifdef PCNET_HAS_PROM + int i; +#endif + + /* Reset the PCnet controller */ + pcnet_reset(dev); + + /* Check if register access is working */ + if (pcnet_read_csr(dev, 0) != 4 || !pcnet_check(dev)) { + printf("%s: CSR register access check failed\n", dev->name); + return -1; + } + + /* Identify the chip */ + chip_version = pcnet_read_csr(dev, 88) | (pcnet_read_csr(dev,89) << 16); + if ((chip_version & 0xfff) != 0x003) + return -1; + chip_version = (chip_version >> 12) & 0xffff; + switch (chip_version) { +#ifdef CONFIG_PCNET_79C973 + case 0x2625: + chipname = "PCnet/FAST III 79C973"; /* PCI */ + break; +#endif +#ifdef CONFIG_PCNET_79C975 + case 0x2627: + chipname = "PCnet/FAST III 79C975"; /* PCI */ + break; +#endif + default: + printf("%s: PCnet version %#x not supported\n", + dev->name, chip_version); + return -1; + } + + DEBUG1("AMD %s\n", chipname); + +#ifdef PCNET_HAS_PROM + /* + * In most chips, after a chip reset, the ethernet address is read from + * the station address PROM at the base address and programmed into the + * "Physical Address Registers" CSR12-14. + */ + for (i = 0; i < 3; i++) { + unsigned int val; + val = pcnet_read_csr(dev, i+12) & 0x0ffff; + /* There may be endianness issues here. */ + dev->dev_addr[2*i] = val & 0x0ff; + dev->dev_addr[2*i+1] = (val >> 8) & 0x0ff; + } +#endif /* PCNET_HAS_PROM */ + + return 0; +} + +static int pcnet_init(struct eth_device* dev, bd_t *bis) +{ + int i, val; + u32 addr; + + DEBUG1("%s: pcnet_init...\n", dev->name); + + /* Switch pcnet to 32bit mode */ + pcnet_write_bcr (dev, 20, 2); + +#ifdef CONFIG_PN62 + /* Setup LED registers */ + val = pcnet_read_bcr (dev, 2) | 0x1000; + pcnet_write_bcr (dev, 2, val); /* enable LEDPE */ + pcnet_write_bcr (dev, 4, 0x5080); /* 100MBit */ + pcnet_write_bcr (dev, 5, 0x40c0); /* LNKSE */ + pcnet_write_bcr (dev, 6, 0x4090); /* TX Activity */ + pcnet_write_bcr (dev, 7, 0x4084); /* RX Activity */ +#endif + + /* Set/reset autoselect bit */ + val = pcnet_read_bcr (dev, 2) & ~2; + val |= 2; + pcnet_write_bcr (dev, 2, val); + + /* Enable auto negotiate, setup, disable fd */ + val = pcnet_read_bcr(dev, 32) & ~0x98; + val |= 0x20; + pcnet_write_bcr(dev, 32, val); + + /* + * We only maintain one structure because the drivers will never + * be used concurrently. In 32bit mode the RX and TX ring entries + * must be aligned on 16-byte boundaries. + */ + if (lp == NULL) { + addr = (u32)malloc(sizeof(pcnet_priv_t) + 0x10); + addr = (addr + 0xf) & ~0xf; + lp = (pcnet_priv_t *)addr; + } + + lp->init_block.mode = cpu_to_le16(0x0000); + lp->init_block.filter[0] = 0x00000000; + lp->init_block.filter[1] = 0x00000000; + + /* + * Initialize the Rx ring. + */ + lp->cur_rx = 0; + for (i = 0; i < RX_RING_SIZE; i++) { + lp->rx_ring[i].base = PCI_TO_MEM_LE(dev, lp->rx_buf[i]); + lp->rx_ring[i].buf_length = cpu_to_le16(-PKT_BUF_SZ); + lp->rx_ring[i].status = cpu_to_le16(0x8000); + DEBUG1("Rx%d: base=0x%x buf_length=0x%x status=0x%x\n", + i, lp->rx_ring[i].base, lp->rx_ring[i].buf_length, + lp->rx_ring[i].status); + } + + /* + * Initialize the Tx ring. The Tx buffer address is filled in as + * needed, but we do need to clear the upper ownership bit. + */ + lp->cur_tx = 0; + for (i = 0; i < TX_RING_SIZE; i++) { + lp->tx_ring[i].base = 0; + lp->tx_ring[i].status = 0; + } + + /* + * Setup Init Block. + */ + DEBUG1("Init block at 0x%p: MAC", &lp->init_block); + + for (i = 0; i < 6; i++) { + lp->init_block.phys_addr[i] = dev->enetaddr[i]; + DEBUG1(" %02x", lp->init_block.phys_addr[i]); + } + + lp->init_block.tlen_rlen = cpu_to_le16(TX_RING_LEN_BITS | + RX_RING_LEN_BITS); + lp->init_block.rx_ring = PCI_TO_MEM_LE(dev, lp->rx_ring); + lp->init_block.tx_ring = PCI_TO_MEM_LE(dev, lp->tx_ring); + + DEBUG1("\ntlen_rlen=0x%x rx_ring=0x%x tx_ring=0x%x\n", + lp->init_block.tlen_rlen, + lp->init_block.rx_ring, lp->init_block.tx_ring); + + /* + * Tell the controller where the Init Block is located. + */ + addr = PCI_TO_MEM(dev, &lp->init_block); + pcnet_write_csr(dev, 1, addr & 0xffff); + pcnet_write_csr(dev, 2, (addr >> 16) & 0xffff); + + pcnet_write_csr (dev, 4, 0x0915); + pcnet_write_csr (dev, 0, 0x0001); /* start */ + + /* Wait for Init Done bit */ + for (i = 10000; i > 0; i--) { + if (pcnet_read_csr (dev, 0) & 0x0100) + break; + udelay(10); + } + if (i <= 0) { + printf("%s: TIMEOUT: controller init failed\n", dev->name); + pcnet_reset (dev); + return 0; + } + + /* + * Finally start network controller operation. + */ + pcnet_write_csr (dev, 0, 0x0002); + + return 1; +} + +static int pcnet_send(struct eth_device* dev, volatile void *packet, int pkt_len) +{ + int i, status; + struct pcnet_tx_head *entry = &lp->tx_ring[lp->cur_tx]; + + DEBUG2("Tx%d: %d bytes from 0x%p ", lp->cur_tx, pkt_len, packet); + + /* Wait for completion by testing the OWN bit */ + for (i = 1000; i > 0; i--) { + status = le16_to_cpu(entry->status); + if ((status & 0x8000) == 0) + break; + udelay(100); + DEBUG2("."); + } + if (i <= 0) { + printf("%s: TIMEOUT: Tx%d failed (status = 0x%x)\n", + dev->name, lp->cur_tx, status); + pkt_len = 0; + goto failure; + } + + /* + * Setup Tx ring. Caution: the write order is important here, + * set the status with the "ownership" bits last. + */ + status = 0x8300; + entry->length = le16_to_cpu(-pkt_len); + entry->misc = 0x00000000; + entry->base = PCI_TO_MEM_LE(dev, packet); + entry->status = le16_to_cpu(status); + + /* Trigger an immediate send poll. */ + pcnet_write_csr (dev, 0, 0x0008); + + failure: + if (++lp->cur_tx >= TX_RING_SIZE) + lp->cur_tx = 0; + + DEBUG2("done\n"); + return pkt_len; +} + +static int pcnet_recv(struct eth_device* dev) +{ + struct pcnet_rx_head *entry; + int pkt_len = 0; + u16 status; + + while (1) { + entry = &lp->rx_ring[lp->cur_rx]; + /* + * If we own the next entry, it's a new packet. Send it up. + */ + if (((status = le16_to_cpu(entry->status)) & 0x8000) != 0) { + break; + } + status >>= 8; + + if (status != 0x03) { /* There was an error. */ + + printf("%s: Rx%d", dev->name, lp->cur_rx); + DEBUG1(" (status=0x%x)", status); + if (status & 0x20) printf(" Frame"); + if (status & 0x10) printf(" Overflow"); + if (status & 0x08) printf(" CRC"); + if (status & 0x04) printf(" Fifo"); + printf(" Error\n"); + entry->status &= le16_to_cpu(0x03ff); + + } else { + + pkt_len = (le32_to_cpu(entry->msg_length) & 0xfff) - 4; + if (pkt_len < 60) { + printf("%s: Rx%d: invalid packet length %d\n", + dev->name, lp->cur_rx, pkt_len); + } else { + NetReceive(lp->rx_buf[lp->cur_rx], pkt_len); + DEBUG2("Rx%d: %d bytes from 0x%p\n", + lp->cur_rx, pkt_len, lp->rx_buf[lp->cur_rx]); + } + } + entry->status |= cpu_to_le16(0x8000); + + if (++lp->cur_rx >= RX_RING_SIZE) + lp->cur_rx = 0; + } + return pkt_len; +} + +static void pcnet_halt(struct eth_device* dev) +{ + int i; + + DEBUG1("%s: pcnet_halt...\n", dev->name); + + /* Reset the PCnet controller */ + pcnet_reset (dev); + + /* Wait for Stop bit */ + for (i = 1000; i > 0; i--) { + if (pcnet_read_csr (dev, 0) & 0x4) + break; + udelay(10); + } + if (i <= 0) { + printf("%s: TIMEOUT: controller reset failed\n", dev->name); + } +} + +#endif diff --git a/include/cmd_bsp.h b/include/cmd_bsp.h index 281432e..35040ee 100644 --- a/include/cmd_bsp.h +++ b/include/cmd_bsp.h @@ -256,6 +256,26 @@ extern int do_wd (cmd_tbl_t *, bd_t *, int, int, char *[]); #endif /* CONFIG_PCIPPC2 , CONFIG_PCIPPC6 */ /* ----------------------------------------------------------------------------*/ +/* ----- PN62 -----------------------------------------------------------------*/ +#if defined(CONFIG_PN62) + +#define CMD_TBL_BSP MK_CMD_TBL_ENTRY( \ + "loadpci", 5, 2, 1, do_loadpci, \ + "loadpci - load binary file over PCI\n", \ + "[addr]\n" \ + " - load binary file over PCI to address 'addr'\n" \ +), MK_CMD_TBL_ENTRY( \ + "led" , 3, 3, 1, do_led, \ + "led - set LED 0..11 on the PN62 board\n", \ + "i fun\n" \ + " - set 'i'th LED to function 'fun'\n" \ +), + +extern int do_loadpci (cmd_tbl_t *, bd_t *, int, int, char *[]); +extern int do_led (cmd_tbl_t *, bd_t *, int, int, char *[]); +#endif /* CONFIG_PN62 */ +/* ----------------------------------------------------------------------------*/ + #else #define CMD_TBL_BSP #endif /* CFG_CMD_BSP */ diff --git a/include/cmd_pci.h b/include/cmd_pci.h index 821668f..ca19cc9 100644 --- a/include/cmd_pci.h +++ b/include/cmd_pci.h @@ -28,17 +28,27 @@ #define _CMD_PCI_H #if (CONFIG_COMMANDS & CFG_CMD_PCI) -#define CMD_TBL_PCIINFO MK_CMD_TBL_ENTRY( \ - "pciinfo", 3, 2, 1, do_pciinfo, \ - "pciinfo - print information about PCI devices\n", \ - "[ bus ]\n" \ - " - print information about PCI devices on PCI-Bus 'bus'\n" \ +#define CMD_TBL_PCI MK_CMD_TBL_ENTRY( \ + "pci", 3, 5, 1, do_pci, \ + "pci - list and access PCI Configuraton Space\n", \ + "[bus] [long]\n" \ + " - short or long list of PCI devices on bus 'bus'\n" \ + "pci header b.d.f\n" \ + " - show header of PCI device 'bus.device.function'\n" \ + "pci display[.b, .w, .l] b.d.f [address] [# of objects]\n" \ + " - display PCI configuration space (CFG)\n" \ + "pci next[.b, .w, .l] b.d.f address\n" \ + " - modify, read and keep CFG address\n" \ + "pci modify[.b, .w, .l] b.d.f address\n" \ + " - modify, auto increment CFG address\n" \ + "pci write[.b, .w, .l] b.d.f address value\n" \ + " - write to CFG address\n" \ ), -int do_pciinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]); +int do_pci (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]); #else -#define CMD_TBL_PCIINFO +#define CMD_TBL_PCI #endif /* CFG_CMD_PCI */ #endif /* _CMD_PCI_H */ diff --git a/include/configs/PN62.h b/include/configs/PN62.h new file mode 100644 index 0000000..ab02965 --- /dev/null +++ b/include/configs/PN62.h @@ -0,0 +1,301 @@ +/* + * (C) Copyright 2002 + * Wolfgang Grandegger, DENX Software Engineering, wg@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 + */ + +/* ------------------------------------------------------------------------- */ + +/* + * board/config.h - configuration options, board specific + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* + * High Level Configuration Options + * (easy to change) + */ + +#define CONFIG_MPC824X 1 +#define CONFIG_MPC8240 1 +#define CONFIG_PN62 1 + +#define CONFIG_CONS_INDEX 1 + + +#define REMOVE_COMMANDS ( CFG_CMD_AUTOSCRIPT | \ + CFG_CMD_LOADS | \ + CFG_CMD_ENV | \ + CFG_CMD_FLASH ) + +#define CONFIG_COMMANDS ( (CONFIG_CMD_DFL & ~REMOVE_COMMANDS) |\ + CFG_CMD_PCI |\ + CFG_CMD_BSP) + +#define CONFIG_BAUDRATE 19200 /* console baudrate */ + +#define CONFIG_BOOTDELAY 1 /* autoboot after n seconds */ + +#define CONFIG_CLOCKS_IN_MHZ 1 /* clocks passsed to Linux in MHz */ + +#define CONFIG_SERVERIP 10.0.0.201 +#define CONFIG_IPADDR 10.0.0.200 +#define CONFIG_ROOTPATH /opt/eldk/ppc_82xx +#define CONFIG_NETMASK 255.255.255.0 +#undef CONFIG_BOOTARGS +#if 0 +/* Boot Linux with NFS root filesystem */ +#define CONFIG_BOOTCOMMAND \ + "setenv verify y;" \ + "setenv bootargs console=ttyS0,19200 mem=31M quiet " \ + "root=/dev/nfs rw nfsroot=$(serverip):$(rootpath) " \ + "ip=$(ipaddr):$(serverip)::$(netmask):pn62:eth0:off;" \ + "loadp 100000; bootm" + /* "tftpboot 100000 pImage; bootm" */ +#else +/* Boot Linux with RAMdisk based filesystem (initrd, BusyBox) */ +#define CONFIG_BOOTCOMMAND \ + "setenv verify n;" \ + "setenv bootargs console=ttyS0,19200 mem=31M quiet " \ + "root=/dev/ram rw " \ + "ip=$(ipaddr):$(serverip)::$(netmask):pn62:eth0:off;" \ + "loadp 200000; bootm" +#endif + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include + + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP 1 /* undef to save memory */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ +#define CFG_LOAD_ADDR 0x00100000 /* default load address */ +#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ + +#define CONFIG_PRAM 1024 /* reserve 1 MB protected RAM */ + +#define CONFIG_MISC_INIT_R 1 /* call misc_init_r() on init */ + +#define CONFIG_SHOW_BOOT_PROGRESS 1 /* Show boot progress on LEDs */ + +/* + * PCI stuff + */ +#define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_PNP /* we need Plug 'n Play */ +#if 0 +#define CONFIG_PCI_SCAN_SHOW /* show PCI auto-scan at boot */ +#endif + +/* + * Networking stuff + */ +#define CONFIG_NET_MULTI /* Multi ethernet cards support */ + +#define CONFIG_PCNET /* there are 2 AMD PCnet 79C973 */ +#define CONFIG_PCNET_79C973 + +#define _IO_BASE 0xfe000000 /* points to PCI I/O space */ + + +/* + * Start addresses for the final memory configuration + * (Set up by the startup code) + * Please note that CFG_SDRAM_BASE _must_ start at 0 + */ +#define CFG_SDRAM_BASE 0x00000000 +#define CFG_MAX_RAM_SIZE 0x10000000 + +#define CFG_RESET_ADDRESS 0xfff00100 + +#undef CFG_RAMBOOT +#define CFG_MONITOR_LEN 0x00030000 +#define CFG_MONITOR_BASE TEXT_BASE + +/*#define CFG_INIT_DATA_SIZE 256*/ +#define CFG_INIT_DATA_SIZE 128 + +#define CFG_INIT_RAM_ADDR 0x40000000 +#define CFG_INIT_RAM_END 0x1000 +#define CFG_INIT_DATA_OFFSET (CFG_INIT_RAM_END - CFG_INIT_DATA_SIZE) + + +#define CFG_NO_FLASH 1 /* There is no FLASH memory */ + +#define CFG_ENV_IS_NOWHERE 1 /* Store ENV in memory only */ +#define CFG_ENV_OFFSET 0x00004000 /* Offset of Environment Sector */ +#define CFG_ENV_SIZE 0x00002000 /* Total Size of Environment Sector */ + +#define CFG_MALLOC_LEN (512 << 10) /* Reserve 512 kB for malloc() */ + +#define CFG_MEMTEST_START 0x00004000 /* memtest works on */ +#define CFG_MEMTEST_END 0x01f00000 /* 0 ... 32 MB in DRAM */ + +/* + * Serial port configuration + */ +#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } + +#define CFG_NS16550 +#define CFG_NS16550_SERIAL + +#define CFG_NS16550_REG_SIZE 1 + +#define CFG_NS16550_CLK 1843200 + +#define CFG_NS16550_COM1 0xff800008 +#define CFG_NS16550_COM2 0xff800000 + +/* + * Low Level Configuration Settings + * (address mappings, register initial values, etc.) + * You should know what you are doing if you make changes here. + */ + +#define CONFIG_SYS_CLK_FREQ 33333333 /* external frequency to pll */ +#define CONFIG_PLL_PCI_TO_MEM_MULTIPLIER 3 + +#define CFG_EUMB_ADDR 0xFCE00000 + +/* MCCR1 */ +#define CFG_ROMNAL 3 /* rom/flash next access time */ +#define CFG_ROMFAL 7 /* rom/flash access time */ + +/* MCCR2 */ +#define CFG_ASRISE 6 /* ASRISE in clocks */ +#define CFG_ASFALL 12 /* ASFALL in clocks */ +#define CFG_REFINT 5600 /* REFINT in clocks */ + +/* MCCR3 */ +#define CFG_BSTOPRE 0x3cf /* Burst To Precharge */ +#define CFG_REFREC 2 /* Refresh to activate interval */ +#define CFG_RDLAT 3 /* data latency from read command */ + +/* MCCR4 */ +#define CFG_PRETOACT 1 /* Precharge to activate interval */ +#define CFG_ACTTOPRE 3 /* Activate to Precharge interval */ +#define CFG_ACTORW 2 /* Activate to R/W */ +#define CFG_SDMODE_CAS_LAT 2 /* SDMODE CAS latency */ +#define CFG_SDMODE_WRAP 0 /* SDMODE Wrap type */ +#define CFG_SDMODE_BURSTLEN 2 /* SDMODE Burst length 2=4, 3=8 */ +#define CFG_REGISTERD_TYPE_BUFFER 1 + +/* Memory bank settings: + * + * only bits 20-29 are actually used from these vales to set the + * start/qend address the upper two bits will be 0, and the lower 20 + * bits will be set to 0x00000 for a start address, or 0xfffff for an + * end address + */ +#define CFG_BANK0_START 0x00000000 +#define CFG_BANK0_END (CFG_MAX_RAM_SIZE - 1) +#define CFG_BANK0_ENABLE 1 +#define CFG_BANK1_START 0x00000000 +#define CFG_BANK1_END 0x00000000 +#define CFG_BANK1_ENABLE 0 +#define CFG_BANK2_START 0x00000000 +#define CFG_BANK2_END 0x00000000 +#define CFG_BANK2_ENABLE 0 +#define CFG_BANK3_START 0x00000000 +#define CFG_BANK3_END 0x00000000 +#define CFG_BANK3_ENABLE 0 +#define CFG_BANK4_START 0x00000000 +#define CFG_BANK4_END 0x00000000 +#define CFG_BANK4_ENABLE 0 +#define CFG_BANK5_START 0x00000000 +#define CFG_BANK5_END 0x00000000 +#define CFG_BANK5_ENABLE 0 +#define CFG_BANK6_START 0x00000000 +#define CFG_BANK6_END 0x00000000 +#define CFG_BANK6_ENABLE 0 +#define CFG_BANK7_START 0x00000000 +#define CFG_BANK7_END 0x00000000 +#define CFG_BANK7_ENABLE 0 + +/* + * Memory bank enable bitmask, specifying which of the banks defined above + * are actually present. MSB is for bank #7, LSB is for bank #0. + */ +#define CFG_BANK_ENABLE 0x01 + +#define CFG_ODCR 0xff /* configures line driver impedances, */ + /* see 8240 book for bit definitions */ +#define CFG_PGMAX 0x32 /* how long the 8240 retains the */ + /* currently accessed page in memory */ + /* see 8240 book for details */ + +/* SDRAM 0 - 256MB */ +#define CFG_IBAT0L (CFG_SDRAM_BASE | BATL_PP_10 | BATL_MEMCOHERENCE) +#define CFG_IBAT0U (CFG_SDRAM_BASE | BATU_BL_256M | BATU_VS | BATU_VP) + +#define CFG_IBAT1L (CFG_INIT_RAM_ADDR | BATL_PP_10 | BATL_MEMCOHERENCE) +#define CFG_IBAT1U (CFG_INIT_RAM_ADDR | BATU_BL_128K | BATU_VS | BATU_VP) + +/* PCI memory space */ +#define CFG_IBAT2L (0x80000000 | BATL_PP_10 | BATL_CACHEINHIBIT) +#define CFG_IBAT2U (0x80000000 | BATU_BL_256M | BATU_VS | BATU_VP) + +/* Config addrs, etc */ +#define CFG_IBAT3L (0xF0000000 | BATL_PP_10 | BATL_CACHEINHIBIT) +#define CFG_IBAT3U (0xF0000000 | BATU_BL_256M | BATU_VS | BATU_VP) + +#define CFG_DBAT0L CFG_IBAT0L +#define CFG_DBAT0U CFG_IBAT0U +#define CFG_DBAT1L CFG_IBAT1L +#define CFG_DBAT1U CFG_IBAT1U +#define CFG_DBAT2L CFG_IBAT2L +#define CFG_DBAT2U CFG_IBAT2U +#define CFG_DBAT3L CFG_IBAT3L +#define CFG_DBAT3U CFG_IBAT3U + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ + +/* + * Cache Configuration + */ +#define CFG_CACHELINE_SIZE 32 /* For MPC8240 CPU */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +# define CFG_CACHELINE_SHIFT 5 /* log base 2 of the above value */ +#endif + + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM 0x02 /* Software reboot */ + + +#endif /* __CONFIG_H */ diff --git a/include/flash.h b/include/flash.h index 28028b6..77e7401 100644 --- a/include/flash.h +++ b/include/flash.h @@ -24,6 +24,7 @@ #ifndef _FLASH_H_ #define _FLASH_H_ +#ifndef CFG_NO_FLASH /*----------------------------------------------------------------------- * FLASH Info: contains chip specific data, per FLASH bank */ @@ -312,4 +313,6 @@ extern int flash_real_protect(flash_info_t *info, long sector, int prot); #define FLASH_ERASE_TIMEOUT 120000 /* timeout for erasing in ms */ #define FLASH_WRITE_TIMEOUT 500 /* timeout for writes in ms */ +#endif /* !CFG_NO_FLASH */ + #endif /* _FLASH_H_ */ diff --git a/include/ppcboot.h b/include/ppcboot.h index 4e09a70..a48e2f0 100644 --- a/include/ppcboot.h +++ b/include/ppcboot.h @@ -100,9 +100,12 @@ typedef struct bd_info { #if defined(CONFIG_HYMOD) hymod_conf_t bi_hymod_conf; /* hymod configuration information */ #endif -#if defined(CFG_GT_6426x) - /* the board has two or three onboard ethernet ports */ +#if defined(CFG_GT_6426x) || defined(CONFIG_PN62) + /* second onboard ethernet port */ unsigned char bi_enet1addr[6]; +#endif +#if defined(CFG_GT_6426x) + /* third onboard ethernet port */ unsigned char bi_enet2addr[6]; #endif #if defined(CONFIG_NX823) @@ -213,7 +216,7 @@ void inline setenv (char *, char *); defined(CONFIG_W7O) || \ defined(CONFIG_WALNUT405) void pci_init (bd_t *); -void pciinfo (int); +void pciinfo (int, int); #endif #if defined(CONFIG_CCM) || defined(CONFIG_COGENT) || \ diff --git a/net/eth.c b/net/eth.c index c083175..ec9269c 100644 --- a/net/eth.c +++ b/net/eth.c @@ -33,6 +33,7 @@ extern int gt6426x_eth_initialize(bd_t *bis); extern int eepro100_initialize(bd_t*); extern int dc21x4x_initialize(bd_t*); +extern int pcnet_initialize(bd_t*); extern int fec_initialize(bd_t*); extern int scc_initialize(bd_t*); @@ -75,6 +76,9 @@ int eth_initialize(bd_t *bis) #ifdef CONFIG_TULIP dc21x4x_initialize(bis); #endif +#ifdef CONFIG_PCNET + pcnet_initialize(bis); +#endif #ifdef CFG_GT_6426x gt6426x_eth_initialize(bis); #endif