diff options
author | wdenk <wdenk> | 2002-11-03 00:24:07 +0000 |
---|---|---|
committer | wdenk <wdenk> | 2002-11-03 00:24:07 +0000 |
commit | c609719b8d1b2dca590e0ed499016d041203e403 (patch) | |
tree | 7ea1755d80903ff972f312a249eb856061d40e15 /board/pn62 | |
parent | 5b1d713721c3ea02549940133f09236783dda1f9 (diff) |
Initial revision
Diffstat (limited to 'board/pn62')
-rw-r--r-- | board/pn62/cmd_pn62.c | 164 | ||||
-rw-r--r-- | board/pn62/misc.c | 235 | ||||
-rw-r--r-- | board/pn62/pn62.c | 216 |
3 files changed, 615 insertions, 0 deletions
diff --git a/board/pn62/cmd_pn62.c b/board/pn62/cmd_pn62.c new file mode 100644 index 0000000000..928f6c0943 --- /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 <common.h> +#include <malloc.h> +#include <net.h> +#include <asm/io.h> +#include <pci.h> +#include <cmd_autoscript.h> +#include <cmd_bsp.h> + +#include "pn62.h" + +#if (CONFIG_COMMANDS & CFG_CMD_BSP) + +extern int do_bootm (cmd_tbl_t *, int, int, char *[]); + +/* + * Command led: controls the various LEDs 0..11 on the PN62 card. + */ +int do_led (cmd_tbl_t *cmdtp, 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, 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, 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/misc.c b/board/pn62/misc.c new file mode 100644 index 0000000000..4f71950f8a --- /dev/null +++ b/board/pn62/misc.c @@ -0,0 +1,235 @@ +/* + * (C) Copyright 2002 Wolfgang Grandegger <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 <common.h> +#include <mpc824x.h> +#include <asm/io.h> +#include <pci.h> + +#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 0000000000..4d87527152 --- /dev/null +++ b/board/pn62/pn62.c @@ -0,0 +1,216 @@ +/* + * (C) Copyright 2002 Wolfgang Grandegger <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 <common.h> +#include <mpc824x.h> +#include <pci.h> + +#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 U-Boot 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 ("Board: 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 (void) +{ + show_startup_phase (4); + pci_mpc824x_init (&hose); + + show_startup_phase (5); + i2155x_init (); + show_startup_phase (6); + am79c95x_init (); + show_startup_phase (7); +} + +int misc_init_r (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + 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 (gd->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 (gd->bd->bi_enet1addr, mac, 6); + } + show_startup_phase (11); + + /* Tell everybody that U-Boot is up and runnig */ + i2155x_write_scrapad (0, 0x12345678); + return (0); +} + +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]); +} |