diff --git a/CHANGELOG b/CHANGELOG index 85394aaf8..64277b1af 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,18 @@ Changes for U-Boot 1.0.2: ====================================================================== +* Patch by Markus Pietrek, 24 Feb 2004: + NS9750 DevBoard added + +* Patch by Pierre AUBERT, 24 Feb 2004 + add USB support for MPC5200 + +* Patch by Steven Scholz, 24 Feb 2004: + - fix MII commands to use values from last command + +* Patch by Torsten Demke, 24 Feb 2004: + Add support for the eXalion platform (SPSW-8240, F-30, F-300) + * Patch by Rahul Shanbhag, 19 Feb 2004: Fixes for for OMAP1610 board: - shift some IRQ specific code to platform.S file diff --git a/CREDITS b/CREDITS index 047240df0..c6ebb4a9a 100644 --- a/CREDITS +++ b/CREDITS @@ -103,6 +103,11 @@ N: Dave Ellis E: DGE@sixnetio.com D: EEPROM Speedup, SXNI855T port +N: Thomas Elste +E: info@elste.org +D: Port for the ModNET50 Board, NET+50 CPU Port +W: http://www.imms.de + N: Daniel Engström E: daniel@omicron.se D: x86 port, Support for sc520_cdp board diff --git a/MAINTAINERS b/MAINTAINERS index f23d9e2f6..b692c19bc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -49,6 +49,10 @@ K FLAGADM MPC823 +Torsten Demke + + eXalion MPC824x + Wolfgang Denk AMX860 MPC860 @@ -289,6 +293,10 @@ Unknown / orphaned boards: # Board CPU # ######################################################################### +Thomas Elste + + modnet50 ARM720T (NET+50) + Peter Figuli wepep250 xscale diff --git a/MAKEALL b/MAKEALL index a09998086..dec6f5360 100644 --- a/MAKEALL +++ b/MAKEALL @@ -73,9 +73,9 @@ LIST_4xx=" \ LIST_824x=" \ A3000 BMW CPC45 CU824 \ - debris MOUSSE MUSENKI MVBLUE \ - OXC PN62 Sandpoint8240 Sandpoint8245 \ - SL8245 utx8245 \ + debris eXalion MOUSSE MUSENKI \ + MVBLUE OXC PN62 Sandpoint8240 \ + Sandpoint8245 SL8245 utx8245 \ " ######################################################################### diff --git a/Makefile b/Makefile index 6dab71930..8c822c6de 100644 --- a/Makefile +++ b/Makefile @@ -671,6 +671,9 @@ CPC45_ROMBOOT_config: unconfig CU824_config: unconfig @./mkconfig $(@:_config=) ppc mpc824x cu824 +eXalion_config: unconfig + @./mkconfig $(@:_config=) ppc mpc824x eXalion + MOUSSE_config: unconfig @./mkconfig $(@:_config=) ppc mpc824x mousse diff --git a/board/eXalion/Makefile b/board/eXalion/Makefile new file mode 100644 index 000000000..110d09db7 --- /dev/null +++ b/board/eXalion/Makefile @@ -0,0 +1,41 @@ +# +# (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 +# + +include $(TOPDIR)/config.mk + +LIB = lib$(BOARD).a + +OBJS = $(BOARD).o +SOBJS = + +$(LIB): .depend $(OBJS) $(SOBJS) + $(AR) crv $@ $^ + +######################################################################### + +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/board/eXalion/config.mk b/board/eXalion/config.mk new file mode 100644 index 000000000..b3f65ebe5 --- /dev/null +++ b/board/eXalion/config.mk @@ -0,0 +1,31 @@ +# +# (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 +# + +# +# Sandpoint boards +# + +#TEXT_BASE = 0x00090000 +TEXT_BASE = 0xFFF00000 + +PLATFORM_CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE) diff --git a/board/eXalion/eXalion.c b/board/eXalion/eXalion.c new file mode 100644 index 000000000..2e3f51998 --- /dev/null +++ b/board/eXalion/eXalion.c @@ -0,0 +1,292 @@ +/* + * (C) Copyright 2000-2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2002 + * Torsten Demke, FORCE Computers GmbH. torsten.demke@fci.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include "piix_pci.h" +#include "eXalion.h" + +int checkboard (void) +{ + ulong busfreq = get_bus_freq (0); + char buf[32]; + + printf ("Board: eXalion MPC824x - CHRP (MAP B)\n"); + printf ("Built: %s at %s\n", __DATE__, __TIME__); + printf ("Local Bus: %s MHz\n", strmhz (buf, busfreq)); + + return 0; +} + +int checkflash (void) +{ + printf ("checkflash\n"); + flash_init (); + 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; + + 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: + return ret; +} + +int misc_init_r (void) +{ + pci_dev_t bdf; + u32 val32; + u8 val8; + + puts ("ISA: "); + bdf = pci_find_device (PIIX4_VENDOR_ID, PIIX4_ISA_DEV_ID, 0); + if (bdf == -1) { + puts ("Unable to find PIIX4 ISA bridge !\n"); + hang (); + } + + /* set device for normal ISA instead EIO */ + pci_read_config_dword (bdf, PCI_CFG_PIIX4_GENCFG, &val32); + val32 |= 0x00000001; + pci_write_config_dword (bdf, PCI_CFG_PIIX4_GENCFG, val32); + printf ("PIIX4 ISA bridge (%d,%d,%d)\n", PCI_BUS (bdf), + PCI_DEV (bdf), PCI_FUNC (bdf)); + + puts ("ISA: "); + bdf = pci_find_device (PIIX4_VENDOR_ID, PIIX4_IDE_DEV_ID, 0); + if (bdf == -1) { + puts ("Unable to find PIIX4 IDE controller !\n"); + hang (); + } + + /* Init BMIBA register */ + /* pci_read_config_dword(bdf, PCI_CFG_PIIX4_BMIBA, &val32); */ + /* val32 |= 0x1000; */ + /* pci_write_config_dword(bdf, PCI_CFG_PIIX4_BMIBA, val32); */ + + /* Enable BUS master and IO access */ + val32 = PCI_COMMAND_MASTER | PCI_COMMAND_IO; + pci_write_config_dword (bdf, PCI_COMMAND, val32); + + /* Set latency */ + pci_read_config_byte (bdf, PCI_LATENCY_TIMER, &val8); + val8 = 0x40; + pci_write_config_byte (bdf, PCI_LATENCY_TIMER, val8); + + /* Enable Primary ATA/IDE */ + pci_read_config_dword (bdf, PCI_CFG_PIIX4_IDETIM, &val32); + /* val32 = 0xa307a307; */ + val32 = 0x00008000; + pci_write_config_dword (bdf, PCI_CFG_PIIX4_IDETIM, val32); + + + printf ("PIIX4 IDE controller (%d,%d,%d)\n", PCI_BUS (bdf), + PCI_DEV (bdf), PCI_FUNC (bdf)); + + /* Try to get FAT working... */ + /* fat_register_read(ide_read); */ + + + return (0); +} + +/* + * Show/Init PCI devices on the specified bus number. + */ + +void pci_eXalion_fixup_irq (struct pci_controller *hose, pci_dev_t dev) +{ + unsigned char line; + + switch (PCI_DEV (dev)) { + case 16: + line = PCI_INT_A; + break; + case 17: + line = PCI_INT_B; + break; + case 18: + line = PCI_INT_C; + break; + case 19: + line = PCI_INT_D; + break; +#if defined (CONFIG_MPC8245) + case 20: + line = PCI_INT_A; + break; + case 21: + line = PCI_INT_B; + break; + case 22: + line = PCI_INT_NA; + break; +#endif + default: + line = PCI_INT_A; + break; + } + pci_hose_write_config_byte (hose, dev, PCI_INTERRUPT_LINE, line); +} + + +/* + * Initialize PCI Devices, report devices found. + */ +#ifndef CONFIG_PCI_PNP +#if defined (CONFIG_MPC8240) +static struct pci_config_table pci_eXalion_config_table[] = { + { + /* Intel 82559ER ethernet controller */ + PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x00, 18, 0x00, + pci_cfgfunc_config_device, {PCI_ENET0_IOADDR, + PCI_ENET0_MEMADDR, + PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER}}, + { + /* Intel 82371AB PIIX4 PCI to ISA bridge */ + PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x00, 20, 0x00, + pci_cfgfunc_config_device, {0, + 0, + PCI_COMMAND_IO | PCI_COMMAND_MASTER}}, + { + /* Intel 82371AB PIIX4 IDE controller */ + PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x00, 20, 0x01, + pci_cfgfunc_config_device, {0, + 0, + PCI_COMMAND_IO | PCI_COMMAND_MASTER}}, + {} +}; +#elif defined (CONFIG_MPC8245) +static struct pci_config_table pci_eXalion_config_table[] = { + { + /* Intel 82559ER ethernet controller */ + PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x00, 17, 0x00, + pci_cfgfunc_config_device, {PCI_ENET0_IOADDR, + PCI_ENET0_MEMADDR, + PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER}}, + { + /* Intel 82559ER ethernet controller */ + PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x00, 18, 0x00, + pci_cfgfunc_config_device, {PCI_ENET1_IOADDR, + PCI_ENET1_MEMADDR, + PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER}}, + { + /* Broadcom BCM5690 Gigabit switch */ + PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x00, 20, 0x00, + pci_cfgfunc_config_device, {PCI_ENET2_IOADDR, + PCI_ENET2_MEMADDR, + PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER}}, + { + /* Broadcom BCM5690 Gigabit switch */ + PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x00, 21, 0x00, + pci_cfgfunc_config_device, {PCI_ENET3_IOADDR, + PCI_ENET3_MEMADDR, + PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER}}, + { + /* Intel 82371AB PIIX4 PCI to ISA bridge */ + PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x00, 22, 0x00, + pci_cfgfunc_config_device, {0, + 0, + PCI_COMMAND_IO | PCI_COMMAND_MASTER}}, + { + /* Intel 82371AB PIIX4 IDE controller */ + PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x00, 22, 0x01, + pci_cfgfunc_config_device, {0, + 0, + PCI_COMMAND_IO | PCI_COMMAND_MASTER}}, + {} +}; +#else +#error Specific type of MPC824x must be defined (i.e. CONFIG_MPC8240) +#endif + +#endif /* #ifndef CONFIG_PCI_PNP */ + +struct pci_controller hose = { +#ifndef CONFIG_PCI_PNP + config_table:pci_eXalion_config_table, + fixup_irq:pci_eXalion_fixup_irq, +#endif +}; + +void pci_init_board (void) +{ + pci_mpc824x_init (&hose); +} diff --git a/board/eXalion/eXalion.h b/board/eXalion/eXalion.h new file mode 100644 index 000000000..8dccabb71 --- /dev/null +++ b/board/eXalion/eXalion.h @@ -0,0 +1,52 @@ +/* + * (C) Copyright 2002 + * Torsten Demke, FORCE Computers GmbH. torsten.demke@fci.com + * + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2002 + * James Dougherty (jfd@broadcom.com) + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __EXALION_H +#define __EXALION_H + +/* IRQ settings */ +#define PCI_INT_NA (0xff) /* PCI Intr. not used */ +#define PCI_INT_A (0x09) /* PCI Intr. A Interrupt Request Line Nr. */ +#define PCI_INT_B (0x0a) /* PCI Intr. B Interrupt Request Line Nr. */ +#define PCI_INT_C (0x0b) /* PCI Intr. C Interrupt Request Line Nr. */ +#define PCI_INT_D (0x0c) /* PCI Intr. D Interrupt Request Line Nr. */ +#if defined (CPU_MPC8245) +#define LN_1_INT PCI_INT_B /* ethernet interrupt level */ +#define LN_2_INT PCI_INT_C /* ethernet interrupt level */ +#define BCM_1_INT PCI_INT_A /* BCM5690 interrupt level */ +#define BCM_2_INT PCI_INT_B /* BCM5690 interrupt level */ +#elif defined (CPU_MPC8240) +#define BCM_INT PCI_INT_B /* BCM5600 interrupt level */ +#define LN_INT PCI_INT_C /* ethernet interrupt level */ +#endif + +#ifndef __ASSEMBLY__ +#endif /* !__ASSEMBLY__ */ + +#endif /* __EXALION_H */ diff --git a/board/eXalion/piix_pci.h b/board/eXalion/piix_pci.h new file mode 100644 index 000000000..b3c9c16cc --- /dev/null +++ b/board/eXalion/piix_pci.h @@ -0,0 +1,172 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2002 + * Torsten Demke, FORCE Computers GmbH. torsten.demke@fci.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#ifndef _PIIX4_PCI_H +#define _PIIX4_PCI_H + +#include +#include +#include +#include +#include + +#define PIIX4_VENDOR_ID 0x8086 +#define PIIX4_ISA_DEV_ID 0x7110 +#define PIIX4_IDE_DEV_ID 0x7111 + +/* Function 0 ISA Bridge */ +#define PCI_CFG_PIIX4_IORT 0x4C /* 8 bit ISA Recovery Timer Reg (default 0x4D) */ +#define PCI_CFG_PIIX4_XBCS 0x4E /* 16 bit XBus Chip select reg (default 0x0003) */ +#define PCI_CFG_PIIX4_PIRQC 0x60 /* PCI IRQ Route Register 4 x 8bit (default )*/ +#define PCI_CFG_PIIX4_SERIRQ 0x64 +#define PCI_CFG_PIIX4_TOM 0x69 +#define PCI_CFG_PIIX4_MSTAT 0x6A +#define PCI_CFG_PIIX4_MBDMA 0x76 +#define PCI_CFG_PIIX4_APICBS 0x80 +#define PCI_CFG_PIIX4_DLC 0x82 +#define PCI_CFG_PIIX4_PDMACFG 0x90 +#define PCI_CFG_PIIX4_DDMABS 0x92 +#define PCI_CFG_PIIX4_GENCFG 0xB0 +#define PCI_CFG_PIIX4_RTCCFG 0xCB + +/* IO Addresses */ +#define PIIX4_ISA_DMA1_CH0BA 0x00 +#define PIIX4_ISA_DMA1_CH0CA 0x01 +#define PIIX4_ISA_DMA1_CH1BA 0x02 +#define PIIX4_ISA_DMA1_CH1CA 0x03 +#define PIIX4_ISA_DMA1_CH2BA 0x04 +#define PIIX4_ISA_DMA1_CH2CA 0x05 +#define PIIX4_ISA_DMA1_CH3BA 0x06 +#define PIIX4_ISA_DMA1_CH3CA 0x07 +#define PIIX4_ISA_DMA1_CMDST 0x08 +#define PIIX4_ISA_DMA1_REQ 0x09 +#define PIIX4_ISA_DMA1_WSBM 0x0A +#define PIIX4_ISA_DMA1_CH_MOD 0x0B +#define PIIX4_ISA_DMA1_CLR_PT 0x0C +#define PIIX4_ISA_DMA1_M_CLR 0x0D +#define PIIX4_ISA_DMA1_CLR_M 0x0E +#define PIIX4_ISA_DMA1_RWAMB 0x0F + +#define PIIX4_ISA_DMA2_CH0BA 0xC0 +#define PIIX4_ISA_DMA2_CH0CA 0xC1 +#define PIIX4_ISA_DMA2_CH1BA 0xC2 +#define PIIX4_ISA_DMA2_CH1CA 0xC3 +#define PIIX4_ISA_DMA2_CH2BA 0xC4 +#define PIIX4_ISA_DMA2_CH2CA 0xC5 +#define PIIX4_ISA_DMA2_CH3BA 0xC6 +#define PIIX4_ISA_DMA2_CH3CA 0xC7 +#define PIIX4_ISA_DMA2_CMDST 0xD0 +#define PIIX4_ISA_DMA2_REQ 0xD2 +#define PIIX4_ISA_DMA2_WSBM 0xD4 +#define PIIX4_ISA_DMA2_CH_MOD 0xD6 +#define PIIX4_ISA_DMA2_CLR_PT 0xD8 +#define PIIX4_ISA_DMA2_M_CLR 0xDA +#define PIIX4_ISA_DMA2_CLR_M 0xDC +#define PIIX4_ISA_DMA2_RWAMB 0xDE + +#define PIIX4_ISA_INT1_ICW1 0x20 +#define PIIX4_ISA_INT1_OCW2 0x20 +#define PIIX4_ISA_INT1_OCW3 0x20 +#define PIIX4_ISA_INT1_ICW2 0x21 +#define PIIX4_ISA_INT1_ICW3 0x21 +#define PIIX4_ISA_INT1_ICW4 0x21 +#define PIIX4_ISA_INT1_OCW1 0x21 + +#define PIIX4_ISA_INT1_ELCR 0x4D0 + +#define PIIX4_ISA_INT2_ICW1 0xA0 +#define PIIX4_ISA_INT2_OCW2 0xA0 +#define PIIX4_ISA_INT2_OCW3 0xA0 +#define PIIX4_ISA_INT2_ICW2 0xA1 +#define PIIX4_ISA_INT2_ICW3 0xA1 +#define PIIX4_ISA_INT2_ICW4 0xA1 +#define PIIX4_ISA_INT2_OCW1 0xA1 +#define PIIX4_ISA_INT2_IMR 0xA1 /* read only */ + +#define PIIX4_ISA_INT2_ELCR 0x4D1 + +#define PIIX4_ISA_TMR0_CNT_ST 0x40 +#define PIIX4_ISA_TMR1_CNT_ST 0x41 +#define PIIX4_ISA_TMR2_CNT_ST 0x42 +#define PIIX4_ISA_TMR_TCW 0x43 + +#define PIIX4_ISA_RST_XBUS 0x60 + +#define PIIX4_ISA_NMI_CNT_ST 0x61 +#define PIIX4_ISA_NMI_ENABLE 0x70 + +#define PIIX4_ISA_RTC_INDEX 0x70 +#define PIIX4_ISA_RTC_DATA 0x71 +#define PIIX4_ISA_RTCEXT_IND 0x70 +#define PIIX4_ISA_RTCEXT_DATA 0x71 + +#define PIIX4_ISA_DMA1_CH2LPG 0x81 +#define PIIX4_ISA_DMA1_CH3LPG 0x82 +#define PIIX4_ISA_DMA1_CH1LPG 0x83 +#define PIIX4_ISA_DMA1_CH0LPG 0x87 +#define PIIX4_ISA_DMA2_CH2LPG 0x89 +#define PIIX4_ISA_DMA2_CH3LPG 0x8A +#define PIIX4_ISA_DMA2_CH1LPG 0x8B +#define PIIX4_ISA_DMA2_LPGRFR 0x8F + +#define PIIX4_ISA_PORT_92 0x92 + +#define PIIX4_ISA_APM_CONTRL 0xB2 +#define PIIX4_ISA_APM_STATUS 0xB3 + +#define PIIX4_ISA_COCPU_ERROR 0xF0 + +/* Function 1 IDE Controller */ +#define PCI_CFG_PIIX4_BMIBA 0x20 +#define PCI_CFG_PIIX4_IDETIM 0x40 +#define PCI_CFG_PIIX4_SIDETIM 0x44 +#define PCI_CFG_PIIX4_UDMACTL 0x48 +#define PCI_CFG_PIIX4_UDMATIM 0x4A + +/* Function 2 USB Controller */ +#define PCI_CFG_PIIX4_SBRNUM 0x60 +#define PCI_CFG_PIIX4_LEGSUP 0xC0 + +/* Function 3 Power Management */ +#define PCI_CFG_PIIX4_PMAB 0x40 +#define PCI_CFG_PIIX4_CNTA 0x44 +#define PCI_CFG_PIIX4_CNTB 0x48 +#define PCI_CFG_PIIX4_GPICTL 0x4C +#define PCI_CFG_PIIX4_DEVRESD 0x50 +#define PCI_CFG_PIIX4_DEVACTA 0x54 +#define PCI_CFG_PIIX4_DEVACTB 0x58 +#define PCI_CFG_PIIX4_DEVRESA 0x5C +#define PCI_CFG_PIIX4_DEVRESB 0x60 +#define PCI_CFG_PIIX4_DEVRESC 0x64 +#define PCI_CFG_PIIX4_DEVRESE 0x68 +#define PCI_CFG_PIIX4_DEVRESF 0x6C +#define PCI_CFG_PIIX4_DEVRESG 0x70 +#define PCI_CFG_PIIX4_DEVRESH 0x74 +#define PCI_CFG_PIIX4_DEVRESI 0x78 +#define PCI_CFG_PIIX4_PMMISC 0x80 +#define PCI_CFG_PIIX4_SMBBA 0x90 + + +#endif /* _PIIX4_PCI_H */ diff --git a/board/eXalion/u-boot.lds b/board/eXalion/u-boot.lds new file mode 100644 index 000000000..98584dcf0 --- /dev/null +++ b/board/eXalion/u-boot.lds @@ -0,0 +1,133 @@ +/* + * (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) + lib_ppc/board.o (.text) + lib_ppc/ppcstring.o (.text) + lib_generic/vsprintf.o (.text) + lib_generic/crc32.o (.text) + lib_generic/zlib.o (.text) + + . = DEFINED(env_offset) ? env_offset : .; + common/environment.o (.text) + + *(.text) + + *(.fixup) + *(.got1) + . = ALIGN(16); + *(.rodata) + *(.rodata1) + *(.rodata.str1.4) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + + /* Read-write section, merged into data segment: */ + . = (. + 0x0FFF) & 0xFFFFF000; + _erotext = .; + PROVIDE (erotext = .); + .reloc : + { + *(.got) + _GOT2_TABLE_ = .; + *(.got2) + _FIXUP_TABLE_ = .; + *(.fixup) + } + __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2; + __fixup_entries = (. - _FIXUP_TABLE_) >> 2; + + .data : + { + *(.data) + *(.data1) + *(.sdata) + *(.sdata2) + *(.dynamic) + CONSTRUCTORS + } + _edata = .; + PROVIDE (edata = .); + + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + . = ALIGN(4096); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(4096); + __init_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + + _end = . ; + PROVIDE (end = .); +} diff --git a/board/ns9750dev/Makefile b/board/ns9750dev/Makefile new file mode 100644 index 000000000..d2718cc68 --- /dev/null +++ b/board/ns9750dev/Makefile @@ -0,0 +1,47 @@ +# +# (C) Copyright 2000, 2001, 2002 +# 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 := ns9750dev.o flash.o led.o +SOBJS := platform.o + +$(LIB): $(OBJS) $(SOBJS) + $(AR) crv $@ $(OBJS) $(SOBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CPPFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +-include .depend + +######################################################################### diff --git a/board/ns9750dev/config.mk b/board/ns9750dev/config.mk new file mode 100644 index 000000000..6a22cee51 --- /dev/null +++ b/board/ns9750dev/config.mk @@ -0,0 +1,16 @@ +####################################################################### +# +# Copyright (C) 2004 by FS Forth-Systeme GmbH. +# Markus Pietrek +# +# @TODO +# Linux-Kernel is expected to be at 0000'8000, entry 0000'8000 +# optionally with a ramdisk at 0080'0000 +# +# we load ourself to 0078'0000 +# +# download area is 0060'0000 +# + + +TEXT_BASE = 0x00780000 diff --git a/board/ns9750dev/flash.c b/board/ns9750dev/flash.c new file mode 100644 index 000000000..e7d65157f --- /dev/null +++ b/board/ns9750dev/flash.c @@ -0,0 +1,477 @@ +/* + * (C) Copyright 2001 + * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net + * + * (C) Copyright 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2003 + * Texas Instruments, + * Kshitij Gupta + * + * 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 + +#define PHYS_FLASH_SECT_SIZE 0x00020000 /* 256 KB sectors (x2) */ +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ + +/* Board support for 1 or 2 flash devices */ +#undef FLASH_PORT_WIDTH32 +#define FLASH_PORT_WIDTH16 + +#ifdef FLASH_PORT_WIDTH16 +#define FLASH_PORT_WIDTH ushort +#define FLASH_PORT_WIDTHV vu_short +#define SWAP(x) __swab16(x) +#else +#define FLASH_PORT_WIDTH ulong +#define FLASH_PORT_WIDTHV vu_long +#define SWAP(x) __swab32(x) +#endif + +#define FPW FLASH_PORT_WIDTH +#define FPWV FLASH_PORT_WIDTHV + +#define mb() __asm__ __volatile__ ("" : : : "memory") + + +/* Flash Organization Structure */ +typedef struct OrgDef { + unsigned int sector_number; + unsigned int sector_size; +} OrgDef; + + +/* Flash Organizations */ +OrgDef OrgIntel_28F256L18T[] = { + {4, 32 * 1024}, /* 4 * 32kBytes sectors */ + {255, 128 * 1024}, /* 255 * 128kBytes sectors */ +}; + + +/*----------------------------------------------------------------------- + * Functions + */ +unsigned long flash_init (void); +static ulong flash_get_size (FPW * addr, flash_info_t * info); +static int write_data (flash_info_t * info, ulong dest, FPW data); +static void flash_get_offsets (ulong base, flash_info_t * info); +void inline spin_wheel (void); +void flash_print_info (flash_info_t * info); +void flash_unprotect_sectors (FPWV * addr); +int flash_erase (flash_info_t * info, int s_first, int s_last); +int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt); + +/*----------------------------------------------------------------------- + */ + +unsigned long flash_init (void) +{ + int i; + ulong size = 0; + for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) { + switch (i) { + case 0: + flash_get_size ((FPW *) PHYS_FLASH_1, &flash_info[i]); + flash_get_offsets (PHYS_FLASH_1, &flash_info[i]); + break; + default: + panic ("configured too many flash banks!\n"); + break; + } + size += flash_info[i].size; + } + + /* Protect monitor and environment sectors + */ + flash_protect (FLAG_PROTECT_SET, + CFG_FLASH_BASE, + CFG_FLASH_BASE + monitor_flash_len - 1, &flash_info[0]); + + flash_protect (FLAG_PROTECT_SET, + CFG_ENV_ADDR, + CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]); + + return size; +} + +/*----------------------------------------------------------------------- + */ +static void flash_get_offsets (ulong base, flash_info_t * info) +{ + int i; + OrgDef *pOrgDef; + + pOrgDef = OrgIntel_28F256L18T; + if (info->flash_id == FLASH_UNKNOWN) { + return; + } + + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) { + for (i = 0; i < info->sector_count; i++) { + if (i > 255) { + info->start[i] = base + (i * 0x8000); + info->protect[i] = 0; + } else { + info->start[i] = base + + (i * PHYS_FLASH_SECT_SIZE); + info->protect[i] = 0; + } + } + } +} + +/*----------------------------------------------------------------------- + */ +void flash_print_info (flash_info_t * info) +{ + int i; + + if (info->flash_id == FLASH_UNKNOWN) { + printf ("missing or unknown FLASH type\n"); + return; + } + + switch (info->flash_id & FLASH_VENDMASK) { + case FLASH_MAN_INTEL: + printf ("INTEL "); + break; + default: + printf ("Unknown Vendor "); + break; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_28F256L18T: + printf ("FLASH 28F256L18T\n"); + break; + default: + printf ("Unknown Chip Type\n"); + break; + } + + printf (" Size: %ld MB in %d Sectors\n", + info->size >> 20, info->sector_count); + + printf (" Sector Start Addresses:"); + for (i = 0; i < info->sector_count; ++i) { + if ((i % 5) == 0) + printf ("\n "); + printf (" %08lX%s", + info->start[i], info->protect[i] ? " (RO)" : " "); + } + printf ("\n"); + return; +} + +/* + * The following code cannot be run from FLASH! + */ +static ulong flash_get_size (FPW * addr, flash_info_t * info) +{ + volatile FPW value; + + /* Write auto select command: read Manufacturer ID */ + addr[0x5555] = (FPW) 0x00AA00AA; + addr[0x2AAA] = (FPW) 0x00550055; + addr[0x5555] = (FPW) 0x00900090; + + mb (); + value = addr[0]; + + switch (value) { + + case (FPW) INTEL_MANUFACT: + info->flash_id = FLASH_MAN_INTEL; + break; + + default: + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + addr[0] = (FPW) 0x00FF00FF; /* restore read mode */ + return (0); /* no or unknown flash */ + } + + mb (); + value = addr[1]; /* device ID */ + switch (value) { + + case (FPW) (INTEL_ID_28F256L18T): + info->flash_id += FLASH_28F256L18T; + info->sector_count = 259; + info->size = 0x02000000; + break; /* => 32 MB */ + + default: + info->flash_id = FLASH_UNKNOWN; + break; + } + + if (info->sector_count > CFG_MAX_FLASH_SECT) { + printf ("** ERROR: sector count %d > max (%d) **\n", + info->sector_count, CFG_MAX_FLASH_SECT); + info->sector_count = CFG_MAX_FLASH_SECT; + } + + addr[0] = (FPW) 0x00FF00FF; /* restore read mode */ + + return (info->size); +} + + +/* unprotects a sector for write and erase + * on some intel parts, this unprotects the entire chip, but it + * wont hurt to call this additional times per sector... + */ +void flash_unprotect_sectors (FPWV * addr) +{ +#define PD_FINTEL_WSMS_READY_MASK 0x0080 + + *addr = (FPW) 0x00500050; /* clear status register */ + + /* this sends the clear lock bit command */ + *addr = (FPW) 0x00600060; + *addr = (FPW) 0x00D000D0; +} + + +/*----------------------------------------------------------------------- + */ + +int flash_erase (flash_info_t * info, int s_first, int s_last) +{ + int flag, prot, sect; + ulong type, start, last; + int rcode = 0; + + if ((s_first < 0) || (s_first > s_last)) { + if (info->flash_id == FLASH_UNKNOWN) { + printf ("- missing\n"); + } else { + printf ("- no sectors to erase\n"); + } + return 1; + } + + type = (info->flash_id & FLASH_VENDMASK); + if ((type != FLASH_MAN_INTEL)) { + printf ("Can't erase unknown flash type %08lx - aborted\n", + info->flash_id); + return 1; + } + + prot = 0; + for (sect = s_first; sect <= s_last; ++sect) { + if (info->protect[sect]) { + prot++; + } + } + + if (prot) { + printf ("- Warning: %d protected sectors will not be erased!\n", + prot); + } else { + printf ("\n"); + } + + + start = get_timer (0); + last = start; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts (); + + /* Start erase on unprotected sectors */ + for (sect = s_first; sect <= s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + FPWV *addr = (FPWV *) (info->start[sect]); + FPW status; + + printf ("Erasing sector %2d ... ", sect); + + flash_unprotect_sectors (addr); + + /* arm simple, non interrupt dependent timer */ + reset_timer_masked (); + + *addr = (FPW) 0x00500050;/* clear status register */ + *addr = (FPW) 0x00200020;/* erase setup */ + *addr = (FPW) 0x00D000D0;/* erase confirm */ + + while (((status = + *addr) & (FPW) 0x00800080) != + (FPW) 0x00800080) { + if (get_timer_masked () > + CFG_FLASH_ERASE_TOUT) { + printf ("Timeout\n"); + /* suspend erase */ + *addr = (FPW) 0x00B000B0; + /* reset to read mode */ + *addr = (FPW) 0x00FF00FF; + rcode = 1; + break; + } + } + + /* clear status register cmd. */ + *addr = (FPW) 0x00500050; + *addr = (FPW) 0x00FF00FF;/* resest to read mode */ + printf (" done\n"); + } + } + return rcode; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + * 4 - Flash not identified + */ + +int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) +{ + ulong cp, wp; + FPW data; + int count, i, l, rc, port_width; + + if (info->flash_id == FLASH_UNKNOWN) { + return 4; + } +/* get lower word aligned address */ +#ifdef FLASH_PORT_WIDTH16 + wp = (addr & ~1); + port_width = 2; +#else + wp = (addr & ~3); + port_width = 4; +#endif + + /* + * handle unaligned start bytes + */ + if ((l = addr - wp) != 0) { + data = 0; + for (i = 0, cp = wp; i < l; ++i, ++cp) { + data = (data << 8) | (*(uchar *) cp); + } + for (; i < port_width && cnt > 0; ++i) { + data = (data << 8) | *src++; + --cnt; + ++cp; + } + for (; cnt == 0 && i < port_width; ++i, ++cp) { + data = (data << 8) | (*(uchar *) cp); + } + + if ((rc = write_data (info, wp, SWAP (data))) != 0) { + return (rc); + } + wp += port_width; + } + + /* + * handle word aligned part + */ + count = 0; + while (cnt >= port_width) { + data = 0; + for (i = 0; i < port_width; ++i) { + data = (data << 8) | *src++; + } + if ((rc = write_data (info, wp, SWAP (data))) != 0) { + return (rc); + } + wp += port_width; + cnt -= port_width; + if (count++ > 0x800) { + spin_wheel (); + count = 0; + } + } + + if (cnt == 0) { + return (0); + } + + /* + * handle unaligned tail bytes + */ + data = 0; + for (i = 0, cp = wp; i < port_width && cnt > 0; ++i, ++cp) { + data = (data << 8) | *src++; + --cnt; + } + for (; i < port_width; ++i, ++cp) { + data = (data << 8) | (*(uchar *) cp); + } + + return (write_data (info, wp, SWAP (data))); +} + +/*----------------------------------------------------------------------- + * Write a word or halfword to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static int write_data (flash_info_t * info, ulong dest, FPW data) +{ + FPWV *addr = (FPWV *) dest; + ulong status; + int flag; + + /* Check if Flash is (sufficiently) erased */ + if ((*addr & data) != data) { + printf ("not erased at %08lx (%x)\n", (ulong) addr, *addr); + return (2); + } + flash_unprotect_sectors (addr); + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts (); + *addr = (FPW) 0x00400040; /* write setup */ + *addr = data; + + /* arm simple, non interrupt dependent timer */ + reset_timer_masked (); + + /* wait while polling the status register */ + while (((status = *addr) & (FPW) 0x00800080) != (FPW) 0x00800080) { + if (get_timer_masked () > CFG_FLASH_WRITE_TOUT) { + *addr = (FPW) 0x00FF00FF; /* restore read mode */ + return (1); + } + } + *addr = (FPW) 0x00FF00FF; /* restore read mode */ + return (0); +} + +void inline spin_wheel (void) +{ + static int p = 0; + static char w[] = "\\/-"; + + printf ("\010%c", w[p]); + (++p == 3) ? (p = 0) : 0; +} diff --git a/board/ns9750dev/led.c b/board/ns9750dev/led.c new file mode 100644 index 000000000..ab27f7b58 --- /dev/null +++ b/board/ns9750dev/led.c @@ -0,0 +1,46 @@ +/*********************************************************************** + * + * Copyright (C) 2004 by FS Forth-Systeme GmbH. + * All rights reserved. + * + * $Id: led.c,v 1.1 2004/02/16 10:37:20 mpietrek Exp $ + * @Author: Markus Pietrek + * @Descr: Defines helper functions for toggeling LEDs + * @Usage: + * @References: [1] + * + * 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 + * + ***********************************************************************/ + +#ifdef CONFIG_STATUS_LED + +#include + +static inline void __led_init( led_id_t mask, int state ) +{ + XXXX; +} + +static inline void __led_toggle( led_id_t mask ) +{ +} + +static inline void __led_set( led_id_t mask, int state ) +{ +} + +#endif /* CONFIG_STATUS_LED */ diff --git a/board/ns9750dev/ns9750dev.c b/board/ns9750dev/ns9750dev.c new file mode 100644 index 000000000..0ea89a5d8 --- /dev/null +++ b/board/ns9750dev/ns9750dev.c @@ -0,0 +1,127 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH + * Marius Groeger + * + * (C) Copyright 2002 + * David Mueller, ELSOFT AG, + * + * (C) Copyright 2003 + * Texas Instruments, + * Kshitij Gupta + * + * Copyright (C) 2004 by FS Forth-Systeme GmbH. + * All rights reserved. + * Markus Pietrek + * derived from omap1610innovator.c + * @References: [1] NS9750 Hardware Reference/December 2003 + * + * 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 +#if defined(CONFIG_NS9750DEV) +# include <./configs/ns9750dev.h> +# include <./ns9750_bbus.h> +#endif + +void flash__init( void ); +void ether__init( void ); + +static inline void delay( unsigned long loops ) +{ + __asm__ volatile ("1:\n" + "subs %0, %1, #1\n" + "bne 1b":"=r" (loops):"0" (loops)); +} + + +/*********************************************************************** + * @Function: board_init + * @Return: 0 + * @Descr: Enables BBUS modules and other devices + ***********************************************************************/ + +int board_init( void ) +{ + DECLARE_GLOBAL_DATA_PTR; + + /* Active BBUS modules */ + *get_bbus_reg_addr( NS9750_BBUS_MASTER_RESET ) = 0; + +#warning TODO check numbers + /* arch number of OMAP 1510-Board */ + /* to be changed for OMAP 1610 Board */ + gd->bd->bi_arch_number = 234; + + /* adress of boot parameters */ + gd->bd->bi_boot_params = 0x10000100; + + +/* this speeds up your boot a quite a bit. However to make it + * work, you need make sure your kernel startup flush bug is fixed. + * ... rkw ... + */ + icache_enable(); + + flash__init(); + ether__init(); + return 0; +} + + +int misc_init_r (void) +{ + /* currently empty */ + return (0); +} + +/****************************** + Routine: + Description: +******************************/ +void flash__init (void) +{ +} +/************************************************************* + Routine:ether__init + Description: take the Ethernet controller out of reset and wait + for the EEPROM load to complete. +*************************************************************/ +void ether__init (void) +{ +} + +/****************************** + Routine: + Description: +******************************/ +int dram_init (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + gd->bd->bi_dram[0].start = PHYS_SDRAM_1; + gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; + +#if CONFIG_NR_DRAM_BANKS > 1 + gd->bd->bi_dram[1].start = PHYS_SDRAM_2; + gd->bd->bi_dram[1].size = PHYS_SDRAM_2_SIZE; +#endif + return 0; +} diff --git a/board/ns9750dev/platform.S b/board/ns9750dev/platform.S new file mode 100644 index 000000000..11f9aef80 --- /dev/null +++ b/board/ns9750dev/platform.S @@ -0,0 +1,298 @@ +/* + * Board specific setup info + * + * (C) Copyright 2003 + * Texas Instruments, + * Kshitij Gupta + * + * Modified for the NS9750 DevBoard by + * (C) Copyright 2004 by FS Forth-Systeme GmbH. + * Markus Pietrek + * @References: [1] NS9750 Hardware Reference/December 2003 + * [2] ns9750_a.cmd from MAJIC configuration + * + * 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 + +#if defined(CONFIG_NS9750DEV) +# ifdef CONFIG_INIT_CRITICAL +# include <./ns9750_sys.h> +# include <./ns9750_mem.h> +# endif +#endif + +/*********************************************************************** + * @Function: write_register_block + * @Return: nothing + * @Descr: Copies the register block of register_offset:register value to + * the registers at base r0. The block is assumed to start in RAM at r1 + * and end at r2. The linked RAM base address of U-Boot is assumed to be + * in r5 while the ROM base address we are running from is r6 + * Uses r3 and r4 as tempory registers + ***********************************************************************/ + +.macro write_register_block + @@ map the addresses to high memory + sub r1, r1, r5 + add r1, r1, r6 + sub r2, r2, r5 + add r2, r2, r6 + + @@ copy all +1: + @@ Write register/value pair starting at [r1] to register base r0 + ldr r3, [r1], #4 + ldr r4, [r1], #4 + str r4, [r0,r3] + cmp r1, r2 + blt 1b +.endm + +_TEXT_BASE: + .word TEXT_BASE @ sdram load addr from config.mk +_PHYS_FLASH: + .word PHYS_FLASH_1 @ real flash address (without mirroring) +_CAS_LATENCY: + .word 0x00022000 @ for CAS2 latency + +#ifdef CONFIG_INIT_CRITICAL +.globl platformsetup +platformsetup: + + /* U-Boot may be linked to RAM at 0x780000. But this code will run in + flash from 0x0. But in order to enable RAM we have to disable the + mirror bit, therefore we have to jump to our real flash address + beginning at PHYS_FLASH_1 (CS4 Base). Therefore, + _run_at_real_flash_address may be 0x500003b0 while be linked to + 0x7803b0. So we must modify our linked addresses */ + + @@ branch to high memory address, away from 0x0 + ldr r5, _TEXT_BASE + ldr r6, _PHYS_FLASH + ldr r0, =_run_at_real_flash_address + sub r0, r0, r5 + add r0, r0, r6 + mov pc, r0 + nop @ for pipelining + +_run_at_real_flash_address: + @@ now we are running > PHYS_FLASH_1, safe to enable memory controller + + @@ Write Memory Configuration Registers + + ldr r0, _NS9750_MEM_MODULE_BASE + ldr r1, =_MEM_CONFIG_START + ldr r2, =_MEM_CONFIG_END + + write_register_block + + @@ Give SDRAM some time to settle + @@ @TODO. According to [2] it should be 2 AHB cycles. Check + + ldr r1, =0x50 +_sdram_settle: + subs r1, r1, #1 + bne _sdram_settle + +_enable_mappings: + @@ Enable SDRAM Mode + + ldr r1, =_MEM_MODE_START + ldr r2, =_MEM_MODE_END + + write_register_block + + ldr r3, _CAS_LATENCY @ perform one read from SDRAM + ldr r3, [r3] + + @@ Enable SDRAM and memory mappings + + ldr r1, =_MEM_ENABLE_START + ldr r2, =_MEM_ENABLE_END + + write_register_block + + @@ Activate AHB monitor + + ldr r0, =NS9750_SYS_MODULE_BASE + ldr r1, =_AHB_MONITOR_START + ldr r2, =_AHB_MONITOR_END + + write_register_block +_relocate_lr: + /* lr and ip (from cpu_init_crit) are still based on 0x0, relocate it to + PHYS_FLASH. */ + mov r1, ip + add r1, r1, r6 + mov ip, r1 + + mov r1, lr + add r1, r1, r6 + mov lr, r1 + + @@ back to arch calling code + mov pc, lr + + .ltorg + +_NS9750_MEM_MODULE_BASE: + .word NS9750_MEM_MODULE_BASE + +_MEM_CONFIG_START: + /* Table of 2 32bit entries. First word is register address offset + relative to NS9750_MEM_MODULE_BASE, second one is value. They are + written in order of appearance */ + + @@ Register values taken from [2] + .word NS9750_MEM_CTRL + .word NS9750_MEM_CTRL_E + + .word NS9750_MEM_DYN_REFRESH + .word (0x6 & NS9750_MEM_DYN_REFRESH_MA) + + .word NS9750_MEM_DYN_READ_CFG + .word (0x1 & NS9750_MEM_DYN_READ_CFG_MA) + + .word NS9750_MEM_DYN_TRP + .word (0x1 & NS9750_MEM_DYN_TRP_MA) + + .word NS9750_MEM_DYN_TRAS + .word (0x4 & NS9750_MEM_DYN_TRAS_MA) + + .word NS9750_MEM_DYN_TAPR + .word (0x1 & NS9750_MEM_DYN_TRAS_MA) + + .word NS9750_MEM_DYN_TDAL + .word (0x5 & NS9750_MEM_DYN_TDAL_MA) + + .word NS9750_MEM_DYN_TWR + .word (0x1 & NS9750_MEM_DYN_TWR_MA) + + .word NS9750_MEM_DYN_TRC + .word (0x6 & NS9750_MEM_DYN_TRC_MA) + + .word NS9750_MEM_DYN_TRFC + .word (0x6 & NS9750_MEM_DYN_TRFC_MA) + + .word NS9750_MEM_DYN_TRRD + .word (0x1 & NS9750_MEM_DYN_TRRD_MA) + + .word NS9750_MEM_DYN_TMRD + .word (0x1 & NS9750_MEM_DYN_TMRD_MA) + + @@ CS 4 + .word NS9750_MEM_DYN_CFG(0) + .word (NS9750_MEM_DYN_CFG_AM | \ + (0x280 & NS9750_MEM_DYN_CFG_AM_MA)) + + .word NS9750_MEM_DYN_RAS_CAS(0) + .word ((0x200 & NS9750_MEM_DYN_RAS_CAS_CAS_MA) | \ + (0x03 & NS9750_MEM_DYN_RAS_CAS_RAS_MA)) + + @@ CS 5 + .word NS9750_MEM_DYN_CFG(1) + .word (NS9750_MEM_DYN_CFG_AM | \ + (0x280 & NS9750_MEM_DYN_CFG_AM_MA)) + + .word NS9750_MEM_DYN_RAS_CAS(1) + .word ((0x200 & NS9750_MEM_DYN_RAS_CAS_CAS_MA) | \ + (0x03 & NS9750_MEM_DYN_RAS_CAS_RAS_MA)) + + @@ CS 6 + .word NS9750_MEM_DYN_CFG(2) + .word (NS9750_MEM_DYN_CFG_AM | \ + (0x280 & NS9750_MEM_DYN_CFG_AM_MA)) + + .word NS9750_MEM_DYN_RAS_CAS(2) + .word ((0x200 & NS9750_MEM_DYN_RAS_CAS_CAS_MA) | \ + (0x03 & NS9750_MEM_DYN_RAS_CAS_RAS_MA)) + + @@ CS 7 + .word NS9750_MEM_DYN_CFG(3) + .word (NS9750_MEM_DYN_CFG_AM | \ + (0x280 & NS9750_MEM_DYN_CFG_AM_MA)) + + .word NS9750_MEM_DYN_RAS_CAS(3) + .word ((0x200 & NS9750_MEM_DYN_RAS_CAS_CAS_MA) | \ + (0x03 & NS9750_MEM_DYN_RAS_CAS_RAS_MA)) + + .word NS9750_MEM_DYN_CTRL + .word (NS9750_MEM_DYN_CTRL_I_PALL | \ + NS9750_MEM_DYN_CTRL_SR | \ + NS9750_MEM_DYN_CTRL_CE ) + + .word NS9750_MEM_DYN_REFRESH + .word (0x1 & NS9750_MEM_DYN_REFRESH_MA) + @@ No further register settings after refresh +_MEM_CONFIG_END: + +_MEM_MODE_START: + .word NS9750_MEM_DYN_REFRESH + .word (0x30 & NS9750_MEM_DYN_REFRESH_MA) + + .word NS9750_MEM_DYN_CTRL + .word (NS9750_MEM_DYN_CTRL_I_MODE | \ + NS9750_MEM_DYN_CTRL_SR | \ + NS9750_MEM_DYN_CTRL_CE ) +_MEM_MODE_END: + +_MEM_ENABLE_START: + .word NS9750_MEM_DYN_CTRL + .word (NS9750_MEM_DYN_CTRL_I_NORMAL | \ + NS9750_MEM_DYN_CTRL_SR | \ + NS9750_MEM_DYN_CTRL_CE ) + + @@ CS 4 + .word NS9750_MEM_DYN_CFG(0) + .word (NS9750_MEM_DYN_CFG_BDMC | \ + NS9750_MEM_DYN_CFG_AM | \ + (0x280 & NS9750_MEM_DYN_CFG_AM_MA)) + + @@ CS 5 + .word NS9750_MEM_DYN_CFG(1) + .word (NS9750_MEM_DYN_CFG_BDMC | \ + NS9750_MEM_DYN_CFG_AM | \ + (0x280 & NS9750_MEM_DYN_CFG_AM_MA)) + + @@ CS 6 + .word NS9750_MEM_DYN_CFG(2) + .word (NS9750_MEM_DYN_CFG_BDMC | \ + NS9750_MEM_DYN_CFG_AM | \ + (0x280 & NS9750_MEM_DYN_CFG_AM_MA)) + + @@ CS 7 + .word NS9750_MEM_DYN_CFG(3) + .word (NS9750_MEM_DYN_CFG_BDMC | \ + NS9750_MEM_DYN_CFG_AM | \ + (0x280 & NS9750_MEM_DYN_CFG_AM_MA)) +_MEM_ENABLE_END: + +_AHB_MONITOR_START: + .word NS9750_SYS_AHB_TIMEOUT + .word 0x01000100 @ @TODO not calculated yet + + .word NS9750_SYS_AHB_MON + .word (NS9750_SYS_AHB_MON_BMTC_GEN_IRQ | \ + NS9750_SYS_AHB_MON_BATC_GEN_IRQ) +_AHB_MONITOR_END: + +#endif /* CONFIG_INIT_CRITICAL */ diff --git a/board/ns9750dev/u-boot.lds b/board/ns9750dev/u-boot.lds new file mode 100644 index 000000000..8a05892af --- /dev/null +++ b/board/ns9750dev/u-boot.lds @@ -0,0 +1,58 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * 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_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/ +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + + . = ALIGN(4); + .data : { *(.data) } + + . = ALIGN(4); + .got : { *(.got) } + + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + + . = ALIGN(4); + __bss_start = .; + .bss : { *(.bss) } + _end = . ; + +} diff --git a/board/omap1610inn/platform.S b/board/omap1610inn/platform.S index 2fa4378b6..441edc28a 100644 --- a/board/omap1610inn/platform.S +++ b/board/omap1610inn/platform.S @@ -41,15 +41,15 @@ _TEXT_BASE: platformsetup: - /*------------------------------------------------------* - *mask all IRQs by setting all bits in the INTMR default* - *------------------------------------------------------*/ + /*------------------------------------------------------* + *mask all IRQs by setting all bits in the INTMR default* + *------------------------------------------------------*/ mov r1, #0xffffffff ldr r0, =REG_IHL1_MIR str r1, [r0] ldr r0, =REG_IHL2_MIR str r1, [r0] - + /*------------------------------------------------------* * Set up ARM CLM registers (IDLECT1) * *------------------------------------------------------*/ diff --git a/common/cmd_mii.c b/common/cmd_mii.c index f8ebef6af..abbdaa2be 100644 --- a/common/cmd_mii.c +++ b/common/cmd_mii.c @@ -129,6 +129,7 @@ int do_mii (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) last_op = op; last_addr = addr; last_data = data; + last_reg = reg; return rcode; } diff --git a/common/usb_storage.c b/common/usb_storage.c index d99f25963..dbe9cd9b8 100644 --- a/common/usb_storage.c +++ b/common/usb_storage.c @@ -19,7 +19,7 @@ * * 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 + * 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 @@ -53,10 +53,12 @@ #ifdef CONFIG_USB_STORAGE -#undef USB_STOR_DEBUG +#undef USB_STOR_DEBUG +#undef BBB_COMDAT_TRACE +#undef BBB_XPORT_TRACE #ifdef USB_STOR_DEBUG -#define USB_STOR_PRINTF(fmt,args...) printf (fmt ,##args) +#define USB_STOR_PRINTF(fmt,args...) printf (fmt ,##args) #else #define USB_STOR_PRINTF(fmt,args...) #endif @@ -102,7 +104,7 @@ typedef struct { # define CBWCDBLENGTH 16 __u8 CBWCDB[CBWCDBLENGTH]; } umass_bbb_cbw_t; -#define UMASS_BBB_CBW_SIZE 31 +#define UMASS_BBB_CBW_SIZE 31 static __u32 CBWTag = 0; /* Command Status Wrapper */ @@ -113,10 +115,10 @@ typedef struct { __u32 dCSWDataResidue; __u8 bCSWStatus; # define CSWSTATUS_GOOD 0x0 -# define CSWSTATUS_FAILED 0x1 +# define CSWSTATUS_FAILED 0x1 # define CSWSTATUS_PHASE 0x2 } umass_bbb_csw_t; -#define UMASS_BBB_CSW_SIZE 13 +#define UMASS_BBB_CSW_SIZE 13 #define USB_MAX_STOR_DEV 5 static int usb_max_devs; /* number of highest available usb device */ @@ -128,7 +130,7 @@ typedef int (*trans_cmnd)(ccb*, struct us_data*); typedef int (*trans_reset)(struct us_data*); struct us_data { - struct usb_device *pusb_dev; /* this usb_device */ + struct usb_device *pusb_dev; /* this usb_device */ unsigned int flags; /* from filter initially */ unsigned char ifnum; /* interface number */ unsigned char ep_in; /* in endpoint */ @@ -136,14 +138,14 @@ struct us_data { unsigned char ep_int; /* interrupt . */ unsigned char subclass; /* as in overview */ unsigned char protocol; /* .............. */ - unsigned char attention_done; /* force attn on first cmd */ + unsigned char attention_done; /* force attn on first cmd */ unsigned short ip_data; /* interrupt data */ int action; /* what to do */ int ip_wanted; /* needed */ int *irq_handle; /* for USB int requests */ unsigned int irqpipe; /* pipe for release_irq */ unsigned char irqmaxp; /* max packed for irq Pipe */ - unsigned char irqinterval; /* Intervall for IRQ Pipe */ + unsigned char irqinterval; /* Intervall for IRQ Pipe */ ccb *srb; /* current srb */ trans_reset transport_reset; /* reset routine */ trans_cmnd transport; /* transport routine */ @@ -152,7 +154,7 @@ struct us_data { static struct us_data usb_stor[USB_MAX_STOR_DEV]; -#define USB_STOR_TRANSPORT_GOOD 0 +#define USB_STOR_TRANSPORT_GOOD 0 #define USB_STOR_TRANSPORT_FAILED -1 #define USB_STOR_TRANSPORT_ERROR -2 @@ -517,45 +519,47 @@ int usb_stor_CB_comdat(ccb *srb, struct us_data *us) } -int usb_stor_CBI_get_status(ccb *srb, struct us_data *us) +int usb_stor_CBI_get_status (ccb * srb, struct us_data *us) { int timeout; - us->ip_wanted=1; - submit_int_msg(us->pusb_dev,us->irqpipe, - (void *)&us->ip_data,us->irqmaxp ,us->irqinterval); - timeout=1000; - while(timeout--) { - if((volatile int *)us->ip_wanted==0) + us->ip_wanted = 1; + submit_int_msg (us->pusb_dev, us->irqpipe, + (void *) &us->ip_data, us->irqmaxp, us->irqinterval); + timeout = 1000; + while (timeout--) { + if ((volatile int *) us->ip_wanted == 0) break; - wait_ms(10); + wait_ms (10); } if (us->ip_wanted) { - printf(" Did not get interrupt on CBI\n"); + printf (" Did not get interrupt on CBI\n"); us->ip_wanted = 0; return USB_STOR_TRANSPORT_ERROR; } - USB_STOR_PRINTF("Got interrupt data 0x%x, transfered %d status 0x%lX\n", us->ip_data,us->pusb_dev->irq_act_len,us->pusb_dev->irq_status); + USB_STOR_PRINTF + ("Got interrupt data 0x%x, transfered %d status 0x%lX\n", + us->ip_data, us->pusb_dev->irq_act_len, + us->pusb_dev->irq_status); /* UFI gives us ASC and ASCQ, like a request sense */ if (us->subclass == US_SC_UFI) { if (srb->cmd[0] == SCSI_REQ_SENSE || srb->cmd[0] == SCSI_INQUIRY) return USB_STOR_TRANSPORT_GOOD; /* Good */ + else if (us->ip_data) + return USB_STOR_TRANSPORT_FAILED; else - if (us->ip_data) - return USB_STOR_TRANSPORT_FAILED; - else - return USB_STOR_TRANSPORT_GOOD; + return USB_STOR_TRANSPORT_GOOD; } /* otherwise, we interpret the data normally */ switch (us->ip_data) { - case 0x0001: - return USB_STOR_TRANSPORT_GOOD; - case 0x0002: - return USB_STOR_TRANSPORT_FAILED; - default: - return USB_STOR_TRANSPORT_ERROR; - } /* switch */ + case 0x0001: + return USB_STOR_TRANSPORT_GOOD; + case 0x0002: + return USB_STOR_TRANSPORT_FAILED; + default: + return USB_STOR_TRANSPORT_ERROR; + } /* switch */ return USB_STOR_TRANSPORT_ERROR; } @@ -601,11 +605,11 @@ int usb_stor_BBB_transport(ccb *srb, struct us_data *us) pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in); pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out); /* DATA phase + error handling */ - USB_STOR_PRINTF("DATA phase\n"); data_actlen = 0; /* no data, go immediately to the STATUS phase */ if (srb->datalen == 0) goto st; + USB_STOR_PRINTF("DATA phase\n"); if (dir_in) pipe = pipein; else @@ -732,7 +736,7 @@ do_retry: } if((us->protocol==US_PR_CBI) && ((srb->cmd[0]==SCSI_REQ_SENSE) || - (srb->cmd[0]==SCSI_INQUIRY))) { /* do not issue an autorequest after request sense */ + (srb->cmd[0]==SCSI_INQUIRY))) { /* do not issue an autorequest after request sense */ USB_STOR_PRINTF("No auto request and good\n"); return USB_STOR_TRANSPORT_GOOD; } @@ -749,7 +753,7 @@ do_retry: USB_STOR_PRINTF("auto request returned %d\n",result); /* if this is an CBI Protocol, get IRQ */ if(us->protocol==US_PR_CBI) { - status=usb_stor_CBI_get_status(psrb,us); + status=usb_stor_CBI_get_status(psrb,us); } if((result<0)&&!(us->pusb_dev->status & USB_ST_STALLED)) { USB_STOR_PRINTF(" AUTO REQUEST ERROR %d\n",us->pusb_dev->status); @@ -765,7 +769,7 @@ do_retry: switch(srb->sense_buf[2]) { case 0x01: /* Recovered Error */ return USB_STOR_TRANSPORT_GOOD; - break; + break; case 0x02: /* Not Ready */ if(notready++ > USB_TRANSPORT_NOT_READY_RETRY) { printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X 0x%02X (NOT READY)\n", @@ -817,7 +821,7 @@ static int usb_inquiry(ccb *srb,struct us_data *ss) static int usb_request_sense(ccb *srb,struct us_data *ss) { char *ptr; - return 0; + ptr=srb->pdata; memset(&srb->cmd[0],0,12); srb->cmd[0]=SCSI_REQ_SENSE; @@ -845,6 +849,8 @@ static int usb_test_unit_ready(ccb *srb,struct us_data *ss) if(ss->transport(srb,ss)==USB_STOR_TRANSPORT_GOOD) { return 0; } + usb_request_sense (srb, ss); + wait_ms (100); } while(retries--); return -1; @@ -1026,7 +1032,7 @@ int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,struct us_data ss->transport_reset = usb_stor_BBB_reset; break; default: - printf("USB Starage Transport unknown / not yet implemented\n"); + printf("USB Storage Transport unknown / not yet implemented\n"); return 0; break; } @@ -1069,8 +1075,10 @@ int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,struct us_data /* set class specific stuff */ /* We only handle certain protocols. Currently, these are * the only ones. + * The SFF8070 accepts the requests used in u-boot */ - if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI) { + if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI && + ss->subclass != US_SC_8070) { printf("Sorry, protocol %d not yet supported.\n",ss->subclass); return 0; } diff --git a/cpu/mpc5xxx/Makefile b/cpu/mpc5xxx/Makefile index a65bc2232..5b5a33bc7 100644 --- a/cpu/mpc5xxx/Makefile +++ b/cpu/mpc5xxx/Makefile @@ -28,7 +28,7 @@ LIB = lib$(CPU).a START = start.o ASOBJS = io.o firmware_sc_task_bestcomm.impl.o firmware_sc_task.impl.o OBJS = i2c.o traps.o cpu.o cpu_init.o speed.o interrupts.o serial.o \ - loadtask.o fec.o pci_mpc5200.o + loadtask.o fec.o pci_mpc5200.o usb_ohci.o all: .depend $(START) $(ASOBJS) $(LIB) diff --git a/cpu/mpc5xxx/usb_ohci.c b/cpu/mpc5xxx/usb_ohci.c new file mode 100644 index 000000000..5b5eac208 --- /dev/null +++ b/cpu/mpc5xxx/usb_ohci.c @@ -0,0 +1,1602 @@ +/* + * URB OHCI HCD (Host Controller Driver) for USB on the MPC5200. + * + * (C) Copyright 2003-2004 + * Gary Jennejohn, DENX Software Engineering + * + * (C) Copyright 2004 + * Pierre Aubert, Staubli Faverges + * + * 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 + * + * Note: Part of this code has been derived from linux + * + */ +/* + * IMPORTANT NOTES + * 1 - this driver is intended for use with USB Mass Storage Devices + * (BBB) ONLY. There is NO support for Interrupt or Isochronous pipes! + */ + +#include + +#ifdef CONFIG_USB_OHCI + +#include +#include +#include "usb_ohci.h" + +#include + +#define OHCI_USE_NPS /* force NoPowerSwitching mode */ +#undef OHCI_VERBOSE_DEBUG /* not always helpful */ +#undef DEBUG +#undef SHOW_INFO +#undef OHCI_FILL_TRACE + +/* For initializing controller (mask in an HCFS mode too) */ +#define OHCI_CONTROL_INIT \ + (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE + +#define readl(a) (*((vu_long *)(a))) +#define writel(a, b) (*((vu_long *)(b)) = ((vu_long)a)) + +#define min_t(type,x,y) ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; }) + +#ifdef DEBUG +#define dbg(format, arg...) printf("DEBUG: " format "\n", ## arg) +#else +#define dbg(format, arg...) do {} while(0) +#endif /* DEBUG */ +#define err(format, arg...) printf("ERROR: " format "\n", ## arg) +#ifdef SHOW_INFO +#define info(format, arg...) printf("INFO: " format "\n", ## arg) +#else +#define info(format, arg...) do {} while(0) +#endif + +#define m16_swap(x) swap_16(x) +#define m32_swap(x) swap_32(x) + +#ifdef CONFIG_MPC5200 +#define ohci_cpu_to_le16(x) (x) +#define ohci_cpu_to_le32(x) (x) +#else +#define ohci_cpu_to_le16(x) swap_16(x) +#define ohci_cpu_to_le32(x) swap_32(x) +#endif + +/* global ohci_t */ +static ohci_t gohci; +/* this must be aligned to a 256 byte boundary */ +struct ohci_hcca ghcca[1]; +/* a pointer to the aligned storage */ +struct ohci_hcca *phcca; +/* this allocates EDs for all possible endpoints */ +struct ohci_device ohci_dev; +/* urb_priv */ +urb_priv_t urb_priv; +/* RHSC flag */ +int got_rhsc; +/* device which was disconnected */ +struct usb_device *devgone; + +/*-------------------------------------------------------------------------*/ + +/* AMD-756 (D2 rev) reports corrupt register contents in some cases. + * The erratum (#4) description is incorrect. AMD's workaround waits + * till some bits (mostly reserved) are clear; ok for all revs. + */ +#define OHCI_QUIRK_AMD756 0xabcd +#define read_roothub(hc, register, mask) ({ \ + u32 temp = readl (&hc->regs->roothub.register); \ + if (hc->flags & OHCI_QUIRK_AMD756) \ + while (temp & mask) \ + temp = readl (&hc->regs->roothub.register); \ + temp; }) + +static u32 roothub_a (struct ohci *hc) + { return read_roothub (hc, a, 0xfc0fe000); } +static inline u32 roothub_b (struct ohci *hc) + { return readl (&hc->regs->roothub.b); } +static inline u32 roothub_status (struct ohci *hc) + { return readl (&hc->regs->roothub.status); } +static u32 roothub_portstatus (struct ohci *hc, int i) + { return read_roothub (hc, portstatus [i], 0xffe0fce0); } + + +/* forward declaration */ +static int hc_interrupt (void); +static void +td_submit_job (struct usb_device * dev, unsigned long pipe, void * buffer, + int transfer_len, struct devrequest * setup, urb_priv_t * urb, int interval); + +/*-------------------------------------------------------------------------* + * URB support functions + *-------------------------------------------------------------------------*/ + +/* free HCD-private data associated with this URB */ + +static void urb_free_priv (urb_priv_t * urb) +{ + int i; + int last; + struct td * td; + + last = urb->length - 1; + if (last >= 0) { + for (i = 0; i <= last; i++) { + td = urb->td[i]; + if (td) { + td->usb_dev = NULL; + urb->td[i] = NULL; + } + } + } +} + +/*-------------------------------------------------------------------------*/ + +#ifdef DEBUG +static int sohci_get_current_frame_number (struct usb_device * dev); + +/* debug| print the main components of an URB + * small: 0) header + data packets 1) just header */ + +static void pkt_print (struct usb_device * dev, unsigned long pipe, void * buffer, + int transfer_len, struct devrequest * setup, char * str, int small) +{ + urb_priv_t * purb = &urb_priv; + + dbg("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,len:%d/%d stat:%#lx", + str, + sohci_get_current_frame_number (dev), + usb_pipedevice (pipe), + usb_pipeendpoint (pipe), + usb_pipeout (pipe)? 'O': 'I', + usb_pipetype (pipe) < 2? (usb_pipeint (pipe)? "INTR": "ISOC"): + (usb_pipecontrol (pipe)? "CTRL": "BULK"), + purb->actual_length, + transfer_len, dev->status); +#ifdef OHCI_VERBOSE_DEBUG + if (!small) { + int i, len; + + if (usb_pipecontrol (pipe)) { + printf (__FILE__ ": cmd(8):"); + for (i = 0; i < 8 ; i++) + printf (" %02x", ((__u8 *) setup) [i]); + printf ("\n"); + } + if (transfer_len > 0 && buffer) { + printf (__FILE__ ": data(%d/%d):", + purb->actual_length, + transfer_len); + len = usb_pipeout (pipe)? + transfer_len: purb->actual_length; + for (i = 0; i < 16 && i < len; i++) + printf (" %02x", ((__u8 *) buffer) [i]); + printf ("%s\n", i < len? "...": ""); + } + } +#endif +} + +/* just for debugging; prints non-empty branches of the int ed tree inclusive iso eds*/ +void ep_print_int_eds (ohci_t *ohci, char * str) { + int i, j; + __u32 * ed_p; + for (i= 0; i < 32; i++) { + j = 5; + ed_p = &(ohci->hcca->int_table [i]); + if (*ed_p == 0) + continue; + printf (__FILE__ ": %s branch int %2d(%2x):", str, i, i); + while (*ed_p != 0 && j--) { + ed_t *ed = (ed_t *)ohci_cpu_to_le32(ed_p); + printf (" ed: %4x;", ed->hwINFO); + ed_p = &ed->hwNextED; + } + printf ("\n"); + } +} + +static void ohci_dump_intr_mask (char *label, __u32 mask) +{ + dbg ("%s: 0x%08x%s%s%s%s%s%s%s%s%s", + label, + mask, + (mask & OHCI_INTR_MIE) ? " MIE" : "", + (mask & OHCI_INTR_OC) ? " OC" : "", + (mask & OHCI_INTR_RHSC) ? " RHSC" : "", + (mask & OHCI_INTR_FNO) ? " FNO" : "", + (mask & OHCI_INTR_UE) ? " UE" : "", + (mask & OHCI_INTR_RD) ? " RD" : "", + (mask & OHCI_INTR_SF) ? " SF" : "", + (mask & OHCI_INTR_WDH) ? " WDH" : "", + (mask & OHCI_INTR_SO) ? " SO" : "" + ); +} + +static void maybe_print_eds (char *label, __u32 value) +{ + ed_t *edp = (ed_t *)value; + + if (value) { + dbg ("%s %08x", label, value); + dbg ("%08x", edp->hwINFO); + dbg ("%08x", edp->hwTailP); + dbg ("%08x", edp->hwHeadP); + dbg ("%08x", edp->hwNextED); + } +} + +static char * hcfs2string (int state) +{ + switch (state) { + case OHCI_USB_RESET: return "reset"; + case OHCI_USB_RESUME: return "resume"; + case OHCI_USB_OPER: return "operational"; + case OHCI_USB_SUSPEND: return "suspend"; + } + return "?"; +} + +/* dump control and status registers */ +static void ohci_dump_status (ohci_t *controller) +{ + struct ohci_regs *regs = controller->regs; + __u32 temp; + + temp = readl (®s->revision) & 0xff; + if (temp != 0x10) + dbg ("spec %d.%d", (temp >> 4), (temp & 0x0f)); + + temp = readl (®s->control); + dbg ("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp, + (temp & OHCI_CTRL_RWE) ? " RWE" : "", + (temp & OHCI_CTRL_RWC) ? " RWC" : "", + (temp & OHCI_CTRL_IR) ? " IR" : "", + hcfs2string (temp & OHCI_CTRL_HCFS), + (temp & OHCI_CTRL_BLE) ? " BLE" : "", + (temp & OHCI_CTRL_CLE) ? " CLE" : "", + (temp & OHCI_CTRL_IE) ? " IE" : "", + (temp & OHCI_CTRL_PLE) ? " PLE" : "", + temp & OHCI_CTRL_CBSR + ); + + temp = readl (®s->cmdstatus); + dbg ("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp, + (temp & OHCI_SOC) >> 16, + (temp & OHCI_OCR) ? " OCR" : "", + (temp & OHCI_BLF) ? " BLF" : "", + (temp & OHCI_CLF) ? " CLF" : "", + (temp & OHCI_HCR) ? " HCR" : "" + ); + + ohci_dump_intr_mask ("intrstatus", readl (®s->intrstatus)); + ohci_dump_intr_mask ("intrenable", readl (®s->intrenable)); + + maybe_print_eds ("ed_periodcurrent", readl (®s->ed_periodcurrent)); + + maybe_print_eds ("ed_controlhead", readl (®s->ed_controlhead)); + maybe_print_eds ("ed_controlcurrent", readl (®s->ed_controlcurrent)); + + maybe_print_eds ("ed_bulkhead", readl (®s->ed_bulkhead)); + maybe_print_eds ("ed_bulkcurrent", readl (®s->ed_bulkcurrent)); + + maybe_print_eds ("donehead", readl (®s->donehead)); +} + +static void ohci_dump_roothub (ohci_t *controller, int verbose) +{ + __u32 temp, ndp, i; + + temp = roothub_a (controller); + ndp = (temp & RH_A_NDP); + + if (verbose) { + dbg ("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp, + ((temp & RH_A_POTPGT) >> 24) & 0xff, + (temp & RH_A_NOCP) ? " NOCP" : "", + (temp & RH_A_OCPM) ? " OCPM" : "", + (temp & RH_A_DT) ? " DT" : "", + (temp & RH_A_NPS) ? " NPS" : "", + (temp & RH_A_PSM) ? " PSM" : "", + ndp + ); + temp = roothub_b (controller); + dbg ("roothub.b: %08x PPCM=%04x DR=%04x", + temp, + (temp & RH_B_PPCM) >> 16, + (temp & RH_B_DR) + ); + temp = roothub_status (controller); + dbg ("roothub.status: %08x%s%s%s%s%s%s", + temp, + (temp & RH_HS_CRWE) ? " CRWE" : "", + (temp & RH_HS_OCIC) ? " OCIC" : "", + (temp & RH_HS_LPSC) ? " LPSC" : "", + (temp & RH_HS_DRWE) ? " DRWE" : "", + (temp & RH_HS_OCI) ? " OCI" : "", + (temp & RH_HS_LPS) ? " LPS" : "" + ); + } + + for (i = 0; i < ndp; i++) { + temp = roothub_portstatus (controller, i); + dbg ("roothub.portstatus [%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s", + i, + temp, + (temp & RH_PS_PRSC) ? " PRSC" : "", + (temp & RH_PS_OCIC) ? " OCIC" : "", + (temp & RH_PS_PSSC) ? " PSSC" : "", + (temp & RH_PS_PESC) ? " PESC" : "", + (temp & RH_PS_CSC) ? " CSC" : "", + + (temp & RH_PS_LSDA) ? " LSDA" : "", + (temp & RH_PS_PPS) ? " PPS" : "", + (temp & RH_PS_PRS) ? " PRS" : "", + (temp & RH_PS_POCI) ? " POCI" : "", + (temp & RH_PS_PSS) ? " PSS" : "", + + (temp & RH_PS_PES) ? " PES" : "", + (temp & RH_PS_CCS) ? " CCS" : "" + ); + } +} + +static void ohci_dump (ohci_t *controller, int verbose) +{ + dbg ("OHCI controller usb-%s state", controller->slot_name); + + /* dumps some of the state we know about */ + ohci_dump_status (controller); + if (verbose) + ep_print_int_eds (controller, "hcca"); + dbg ("hcca frame #%04x", controller->hcca->frame_no); + ohci_dump_roothub (controller, 1); +} + + +#endif /* DEBUG */ + +/*-------------------------------------------------------------------------* + * Interface functions (URB) + *-------------------------------------------------------------------------*/ + +/* get a transfer request */ + +int sohci_submit_job(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, struct devrequest *setup, int interval) +{ + ohci_t *ohci; + ed_t * ed; + urb_priv_t *purb_priv; + int i, size = 0; + + ohci = &gohci; + + /* when controller's hung, permit only roothub cleanup attempts + * such as powering down ports */ + if (ohci->disabled) { + err("sohci_submit_job: EPIPE"); + return -1; + } + + /* every endpoint has a ed, locate and fill it */ + if (!(ed = ep_add_ed (dev, pipe))) { + err("sohci_submit_job: ENOMEM"); + return -1; + } + + /* for the private part of the URB we need the number of TDs (size) */ + switch (usb_pipetype (pipe)) { + case PIPE_BULK: /* one TD for every 4096 Byte */ + size = (transfer_len - 1) / 4096 + 1; + break; + case PIPE_CONTROL: /* 1 TD for setup, 1 for ACK and 1 for every 4096 B */ + size = (transfer_len == 0)? 2: + (transfer_len - 1) / 4096 + 3; + break; + } + + if (size >= (N_URB_TD - 1)) { + err("need %d TDs, only have %d", size, N_URB_TD); + return -1; + } + purb_priv = &urb_priv; + purb_priv->pipe = pipe; + + /* fill the private part of the URB */ + purb_priv->length = size; + purb_priv->ed = ed; + purb_priv->actual_length = 0; + + /* allocate the TDs */ + /* note that td[0] was allocated in ep_add_ed */ + for (i = 0; i < size; i++) { + purb_priv->td[i] = td_alloc (dev); + if (!purb_priv->td[i]) { + purb_priv->length = i; + urb_free_priv (purb_priv); + err("sohci_submit_job: ENOMEM"); + return -1; + } + } + + if (ed->state == ED_NEW || (ed->state & ED_DEL)) { + urb_free_priv (purb_priv); + err("sohci_submit_job: EINVAL"); + return -1; + } + + /* link the ed into a chain if is not already */ + if (ed->state != ED_OPER) + ep_link (ohci, ed); + + /* fill the TDs and link it to the ed */ + td_submit_job(dev, pipe, buffer, transfer_len, setup, purb_priv, interval); + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +#ifdef DEBUG +/* tell us the current USB frame number */ + +static int sohci_get_current_frame_number (struct usb_device *usb_dev) +{ + ohci_t *ohci = &gohci; + + return ohci_cpu_to_le16 (ohci->hcca->frame_no); +} +#endif + +/*-------------------------------------------------------------------------* + * ED handling functions + *-------------------------------------------------------------------------*/ + +/* link an ed into one of the HC chains */ + +static int ep_link (ohci_t *ohci, ed_t *edi) +{ + volatile ed_t *ed = edi; + + ed->state = ED_OPER; + + switch (ed->type) { + case PIPE_CONTROL: + ed->hwNextED = 0; + if (ohci->ed_controltail == NULL) { + writel (ed, &ohci->regs->ed_controlhead); + } else { + ohci->ed_controltail->hwNextED = ohci_cpu_to_le32 (ed); + } + ed->ed_prev = ohci->ed_controltail; + if (!ohci->ed_controltail && !ohci->ed_rm_list[0] && + !ohci->ed_rm_list[1] && !ohci->sleeping) { + ohci->hc_control |= OHCI_CTRL_CLE; + writel (ohci->hc_control, &ohci->regs->control); + } + ohci->ed_controltail = edi; + break; + + case PIPE_BULK: + ed->hwNextED = 0; + if (ohci->ed_bulktail == NULL) { + writel (ed, &ohci->regs->ed_bulkhead); + } else { + ohci->ed_bulktail->hwNextED = ohci_cpu_to_le32 (ed); + } + ed->ed_prev = ohci->ed_bulktail; + if (!ohci->ed_bulktail && !ohci->ed_rm_list[0] && + !ohci->ed_rm_list[1] && !ohci->sleeping) { + ohci->hc_control |= OHCI_CTRL_BLE; + writel (ohci->hc_control, &ohci->regs->control); + } + ohci->ed_bulktail = edi; + break; + } + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* unlink an ed from one of the HC chains. + * just the link to the ed is unlinked. + * the link from the ed still points to another operational ed or 0 + * so the HC can eventually finish the processing of the unlinked ed */ + +static int ep_unlink (ohci_t *ohci, ed_t *edi) +{ + volatile ed_t *ed = edi; + + ed->hwINFO |= ohci_cpu_to_le32 (OHCI_ED_SKIP); + + switch (ed->type) { + case PIPE_CONTROL: + if (ed->ed_prev == NULL) { + if (!ed->hwNextED) { + ohci->hc_control &= ~OHCI_CTRL_CLE; + writel (ohci->hc_control, &ohci->regs->control); + } + writel (ohci_cpu_to_le32 (*((__u32 *)&ed->hwNextED)), &ohci->regs->ed_controlhead); + } else { + ed->ed_prev->hwNextED = ed->hwNextED; + } + if (ohci->ed_controltail == ed) { + ohci->ed_controltail = ed->ed_prev; + } else { + ((ed_t *)ohci_cpu_to_le32 (*((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev; + } + break; + + case PIPE_BULK: + if (ed->ed_prev == NULL) { + if (!ed->hwNextED) { + ohci->hc_control &= ~OHCI_CTRL_BLE; + writel (ohci->hc_control, &ohci->regs->control); + } + writel (ohci_cpu_to_le32 (*((__u32 *)&ed->hwNextED)), &ohci->regs->ed_bulkhead); + } else { + ed->ed_prev->hwNextED = ed->hwNextED; + } + if (ohci->ed_bulktail == ed) { + ohci->ed_bulktail = ed->ed_prev; + } else { + ((ed_t *)ohci_cpu_to_le32 (*((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev; + } + break; + } + ed->state = ED_UNLINK; + return 0; +} + + +/*-------------------------------------------------------------------------*/ + +/* add/reinit an endpoint; this should be done once at the usb_set_configuration command, + * but the USB stack is a little bit stateless so we do it at every transaction + * if the state of the ed is ED_NEW then a dummy td is added and the state is changed to ED_UNLINK + * in all other cases the state is left unchanged + * the ed info fields are setted anyway even though most of them should not change */ + +static ed_t * ep_add_ed (struct usb_device *usb_dev, unsigned long pipe) +{ + td_t *td; + ed_t *ed_ret; + volatile ed_t *ed; + + ed = ed_ret = &ohci_dev.ed[(usb_pipeendpoint (pipe) << 1) | + (usb_pipecontrol (pipe)? 0: usb_pipeout (pipe))]; + + if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) { + err("ep_add_ed: pending delete"); + /* pending delete request */ + return NULL; + } + + if (ed->state == ED_NEW) { + ed->hwINFO = ohci_cpu_to_le32 (OHCI_ED_SKIP); /* skip ed */ + /* dummy td; end of td list for ed */ + td = td_alloc (usb_dev); + ed->hwTailP = ohci_cpu_to_le32 (td); + ed->hwHeadP = ed->hwTailP; + ed->state = ED_UNLINK; + ed->type = usb_pipetype (pipe); + ohci_dev.ed_cnt++; + } + + ed->hwINFO = ohci_cpu_to_le32 (usb_pipedevice (pipe) + | usb_pipeendpoint (pipe) << 7 + | (usb_pipeisoc (pipe)? 0x8000: 0) + | (usb_pipecontrol (pipe)? 0: (usb_pipeout (pipe)? 0x800: 0x1000)) + | usb_pipeslow (pipe) << 13 + | usb_maxpacket (usb_dev, pipe) << 16); + + return ed_ret; +} + +/*-------------------------------------------------------------------------* + * TD handling functions + *-------------------------------------------------------------------------*/ + +/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */ + +static void td_fill (ohci_t *ohci, unsigned int info, + void *data, int len, + struct usb_device *dev, int index, urb_priv_t *urb_priv) +{ + volatile td_t *td, *td_pt; +#ifdef OHCI_FILL_TRACE + int i; +#endif + + if (index > urb_priv->length) { + err("index > length"); + return; + } + /* use this td as the next dummy */ + td_pt = urb_priv->td [index]; + td_pt->hwNextTD = 0; + + /* fill the old dummy TD */ + td = urb_priv->td [index] = (td_t *)(ohci_cpu_to_le32 (urb_priv->ed->hwTailP) & ~0xf); + + td->ed = urb_priv->ed; + td->next_dl_td = NULL; + td->index = index; + td->data = (__u32)data; +#ifdef OHCI_FILL_TRACE + if ((usb_pipetype(urb_priv->pipe) == PIPE_BULK) && usb_pipeout(urb_priv->pipe)) { + for (i = 0; i < len; i++) + printf("td->data[%d] %#2x ",i, ((unsigned char *)td->data)[i]); + printf("\n"); + } +#endif + if (!len) + data = 0; + + td->hwINFO = ohci_cpu_to_le32 (info); + td->hwCBP = ohci_cpu_to_le32 (data); + if (data) + td->hwBE = ohci_cpu_to_le32 (data + len - 1); + else + td->hwBE = 0; + td->hwNextTD = ohci_cpu_to_le32 (td_pt); + td->hwPSW [0] = ohci_cpu_to_le16 (((__u32)data & 0x0FFF) | 0xE000); + + /* append to queue */ + td->ed->hwTailP = td->hwNextTD; +} + +/*-------------------------------------------------------------------------*/ + +/* prepare all TDs of a transfer */ + +static void td_submit_job (struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, struct devrequest *setup, urb_priv_t *urb, int interval) +{ + ohci_t *ohci = &gohci; + int data_len = transfer_len; + void *data; + int cnt = 0; + __u32 info = 0; + unsigned int toggle = 0; + + /* OHCI handles the DATA-toggles itself, we just use the USB-toggle bits for reseting */ + if(usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe))) { + toggle = TD_T_TOGGLE; + } else { + toggle = TD_T_DATA0; + usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 1); + } + urb->td_cnt = 0; + if (data_len) + data = buffer; + else + data = 0; + + switch (usb_pipetype (pipe)) { + case PIPE_BULK: + info = usb_pipeout (pipe)? + TD_CC | TD_DP_OUT : TD_CC | TD_DP_IN ; + while(data_len > 4096) { + td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, 4096, dev, cnt, urb); + data += 4096; data_len -= 4096; cnt++; + } + info = usb_pipeout (pipe)? + TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ; + td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, data_len, dev, cnt, urb); + cnt++; + + if (!ohci->sleeping) + writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */ + break; + + case PIPE_CONTROL: + info = TD_CC | TD_DP_SETUP | TD_T_DATA0; + td_fill (ohci, info, setup, 8, dev, cnt++, urb); + if (data_len > 0) { + info = usb_pipeout (pipe)? + TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 : TD_CC | TD_R | TD_DP_IN | TD_T_DATA1; + /* NOTE: mishandles transfers >8K, some >4K */ + td_fill (ohci, info, data, data_len, dev, cnt++, urb); + } + info = usb_pipeout (pipe)? + TD_CC | TD_DP_IN | TD_T_DATA1: TD_CC | TD_DP_OUT | TD_T_DATA1; + td_fill (ohci, info, data, 0, dev, cnt++, urb); + if (!ohci->sleeping) + writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */ + break; + } + if (urb->length != cnt) + dbg("TD LENGTH %d != CNT %d", urb->length, cnt); +} + +/*-------------------------------------------------------------------------* + * Done List handling functions + *-------------------------------------------------------------------------*/ + + +/* calculate the transfer length and update the urb */ + +static void dl_transfer_length(td_t * td) +{ + __u32 tdINFO, tdBE, tdCBP; + urb_priv_t *lurb_priv = &urb_priv; + + tdINFO = ohci_cpu_to_le32 (td->hwINFO); + tdBE = ohci_cpu_to_le32 (td->hwBE); + tdCBP = ohci_cpu_to_le32 (td->hwCBP); + + + if (!(usb_pipetype (lurb_priv->pipe) == PIPE_CONTROL && + ((td->index == 0) || (td->index == lurb_priv->length - 1)))) { + if (tdBE != 0) { + if (td->hwCBP == 0) + lurb_priv->actual_length += tdBE - td->data + 1; + else + lurb_priv->actual_length += tdCBP - td->data; + } + } +} + +/*-------------------------------------------------------------------------*/ + +/* replies to the request have to be on a FIFO basis so + * we reverse the reversed done-list */ + +static td_t * dl_reverse_done_list (ohci_t *ohci) +{ + __u32 td_list_hc; + td_t *td_rev = NULL; + td_t *td_list = NULL; + urb_priv_t *lurb_priv = NULL; + + td_list_hc = ohci_cpu_to_le32 (ohci->hcca->done_head) & 0xfffffff0; + ohci->hcca->done_head = 0; + + while (td_list_hc) { + td_list = (td_t *)td_list_hc; + + if (TD_CC_GET (ohci_cpu_to_le32 (td_list->hwINFO))) { + lurb_priv = &urb_priv; + dbg(" USB-error/status: %x : %p", + TD_CC_GET (ohci_cpu_to_le32 (td_list->hwINFO)), td_list); + if (td_list->ed->hwHeadP & ohci_cpu_to_le32 (0x1)) { + if (lurb_priv && ((td_list->index + 1) < lurb_priv->length)) { + td_list->ed->hwHeadP = + (lurb_priv->td[lurb_priv->length - 1]->hwNextTD & ohci_cpu_to_le32 (0xfffffff0)) | + (td_list->ed->hwHeadP & ohci_cpu_to_le32 (0x2)); + lurb_priv->td_cnt += lurb_priv->length - td_list->index - 1; + } else + td_list->ed->hwHeadP &= ohci_cpu_to_le32 (0xfffffff2); + } +#ifdef CONFIG_MPC5200 + td_list->hwNextTD = 0; +#endif + } + + td_list->next_dl_td = td_rev; + td_rev = td_list; + td_list_hc = ohci_cpu_to_le32 (td_list->hwNextTD) & 0xfffffff0; + } + return td_list; +} + +/*-------------------------------------------------------------------------*/ + +/* td done list */ +static int dl_done_list (ohci_t *ohci, td_t *td_list) +{ + td_t *td_list_next = NULL; + ed_t *ed; + int cc = 0; + int stat = 0xff; + /* urb_t *urb; */ + urb_priv_t *lurb_priv; + __u32 tdINFO, edHeadP, edTailP; + + while (td_list) { + td_list_next = td_list->next_dl_td; + + lurb_priv = &urb_priv; + tdINFO = ohci_cpu_to_le32 (td_list->hwINFO); + + ed = td_list->ed; + + dl_transfer_length(td_list); + + /* error code of transfer */ + cc = TD_CC_GET (tdINFO); + if (++(lurb_priv->td_cnt) == lurb_priv->length) { + if ((ed->state & (ED_OPER | ED_UNLINK)) + && (lurb_priv->state != URB_DEL)) { + dbg("ConditionCode %#x", cc); + stat = cc_to_error[cc]; + } + } + + if (ed->state != ED_NEW) { + edHeadP = ohci_cpu_to_le32 (ed->hwHeadP) & 0xfffffff0; + edTailP = ohci_cpu_to_le32 (ed->hwTailP); + + /* unlink eds if they are not busy */ + if ((edHeadP == edTailP) && (ed->state == ED_OPER)) + ep_unlink (ohci, ed); + } + + td_list = td_list_next; + } + return stat; +} + +/*-------------------------------------------------------------------------* + * Virtual Root Hub + *-------------------------------------------------------------------------*/ + +/* Device descriptor */ +static __u8 root_hub_dev_des[] = +{ + 0x12, /* __u8 bLength; */ + 0x01, /* __u8 bDescriptorType; Device */ + 0x10, /* __u16 bcdUSB; v1.1 */ + 0x01, + 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ + 0x00, /* __u8 bDeviceSubClass; */ + 0x00, /* __u8 bDeviceProtocol; */ + 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ + 0x00, /* __u16 idVendor; */ + 0x00, + 0x00, /* __u16 idProduct; */ + 0x00, + 0x00, /* __u16 bcdDevice; */ + 0x00, + 0x00, /* __u8 iManufacturer; */ + 0x01, /* __u8 iProduct; */ + 0x00, /* __u8 iSerialNumber; */ + 0x01 /* __u8 bNumConfigurations; */ +}; + + +/* Configuration descriptor */ +static __u8 root_hub_config_des[] = +{ + 0x09, /* __u8 bLength; */ + 0x02, /* __u8 bDescriptorType; Configuration */ + 0x19, /* __u16 wTotalLength; */ + 0x00, + 0x01, /* __u8 bNumInterfaces; */ + 0x01, /* __u8 bConfigurationValue; */ + 0x00, /* __u8 iConfiguration; */ + 0x40, /* __u8 bmAttributes; + Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */ + 0x00, /* __u8 MaxPower; */ + + /* interface */ + 0x09, /* __u8 if_bLength; */ + 0x04, /* __u8 if_bDescriptorType; Interface */ + 0x00, /* __u8 if_bInterfaceNumber; */ + 0x00, /* __u8 if_bAlternateSetting; */ + 0x01, /* __u8 if_bNumEndpoints; */ + 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ + 0x00, /* __u8 if_bInterfaceSubClass; */ + 0x00, /* __u8 if_bInterfaceProtocol; */ + 0x00, /* __u8 if_iInterface; */ + + /* endpoint */ + 0x07, /* __u8 ep_bLength; */ + 0x05, /* __u8 ep_bDescriptorType; Endpoint */ + 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ + 0x03, /* __u8 ep_bmAttributes; Interrupt */ + 0x02, /* __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */ + 0x00, + 0xff /* __u8 ep_bInterval; 255 ms */ +}; + +static unsigned char root_hub_str_index0[] = +{ + 0x04, /* __u8 bLength; */ + 0x03, /* __u8 bDescriptorType; String-descriptor */ + 0x09, /* __u8 lang ID */ + 0x04, /* __u8 lang ID */ +}; + +static unsigned char root_hub_str_index1[] = +{ + 28, /* __u8 bLength; */ + 0x03, /* __u8 bDescriptorType; String-descriptor */ + 'O', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'H', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'C', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'I', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + ' ', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'R', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'o', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'o', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 't', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + ' ', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'H', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'u', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'b', /* __u8 Unicode */ + 0, /* __u8 Unicode */ +}; + +/* Hub class-specific descriptor is constructed dynamically */ + + +/*-------------------------------------------------------------------------*/ + +#define OK(x) len = (x); break +#ifdef DEBUG +#define WR_RH_STAT(x) {info("WR:status %#8x", (x));writel((x), &gohci.regs->roothub.status);} +#define WR_RH_PORTSTAT(x) {info("WR:portstatus[%d] %#8x", wIndex-1, (x));writel((x), &gohci.regs->roothub.portstatus[wIndex-1]);} +#else +#define WR_RH_STAT(x) writel((x), &gohci.regs->roothub.status) +#define WR_RH_PORTSTAT(x) writel((x), &gohci.regs->roothub.portstatus[wIndex-1]) +#endif +#define RD_RH_STAT roothub_status(&gohci) +#define RD_RH_PORTSTAT roothub_portstatus(&gohci,wIndex-1) + +/* request to virtual root hub */ + +int rh_check_port_status(ohci_t *controller) +{ + __u32 temp, ndp, i; + int res; + + res = -1; + temp = roothub_a (controller); + ndp = (temp & RH_A_NDP); + for (i = 0; i < ndp; i++) { + temp = roothub_portstatus (controller, i); + /* check for a device disconnect */ + if (((temp & (RH_PS_PESC | RH_PS_CSC)) == + (RH_PS_PESC | RH_PS_CSC)) && + ((temp & RH_PS_CCS) == 0)) { + res = i; + break; + } + } + return res; +} + +static int ohci_submit_rh_msg(struct usb_device *dev, unsigned long pipe, + void *buffer, int transfer_len, struct devrequest *cmd) +{ + void * data = buffer; + int leni = transfer_len; + int len = 0; + int stat = 0; + __u32 datab[4]; + __u8 *data_buf = (__u8 *)datab; + __u16 bmRType_bReq; + __u16 wValue; + __u16 wIndex; + __u16 wLength; + +#ifdef DEBUG +urb_priv.actual_length = 0; +pkt_print(dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe)); +#endif + if ((pipe & PIPE_INTERRUPT) == PIPE_INTERRUPT) { + info("Root-Hub submit IRQ: NOT implemented"); + return 0; + } + + bmRType_bReq = cmd->requesttype | (cmd->request << 8); + wValue = m16_swap (cmd->value); + wIndex = m16_swap (cmd->index); + wLength = m16_swap (cmd->length); + + info("Root-Hub: adr: %2x cmd(%1x): %08x %04x %04x %04x", + dev->devnum, 8, bmRType_bReq, wValue, wIndex, wLength); + + switch (bmRType_bReq) { + /* Request Destination: + without flags: Device, + RH_INTERFACE: interface, + RH_ENDPOINT: endpoint, + RH_CLASS means HUB here, + RH_OTHER | RH_CLASS almost ever means HUB_PORT here + */ + + case RH_GET_STATUS: + *(__u16 *) data_buf = m16_swap (1); OK (2); + case RH_GET_STATUS | RH_INTERFACE: + *(__u16 *) data_buf = m16_swap (0); OK (2); + case RH_GET_STATUS | RH_ENDPOINT: + *(__u16 *) data_buf = m16_swap (0); OK (2); + case RH_GET_STATUS | RH_CLASS: + *(__u32 *) data_buf = m32_swap ( + RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE)); + OK (4); + case RH_GET_STATUS | RH_OTHER | RH_CLASS: + *(__u32 *) data_buf = m32_swap (RD_RH_PORTSTAT); OK (4); + + case RH_CLEAR_FEATURE | RH_ENDPOINT: + switch (wValue) { + case (RH_ENDPOINT_STALL): OK (0); + } + break; + + case RH_CLEAR_FEATURE | RH_CLASS: + switch (wValue) { + case RH_C_HUB_LOCAL_POWER: + OK(0); + case (RH_C_HUB_OVER_CURRENT): + WR_RH_STAT(RH_HS_OCIC); OK (0); + } + break; + + case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: + switch (wValue) { + case (RH_PORT_ENABLE): + WR_RH_PORTSTAT (RH_PS_CCS ); OK (0); + case (RH_PORT_SUSPEND): + WR_RH_PORTSTAT (RH_PS_POCI); OK (0); + case (RH_PORT_POWER): + WR_RH_PORTSTAT (RH_PS_LSDA); OK (0); + case (RH_C_PORT_CONNECTION): + WR_RH_PORTSTAT (RH_PS_CSC ); OK (0); + case (RH_C_PORT_ENABLE): + WR_RH_PORTSTAT (RH_PS_PESC); OK (0); + case (RH_C_PORT_SUSPEND): + WR_RH_PORTSTAT (RH_PS_PSSC); OK (0); + case (RH_C_PORT_OVER_CURRENT): + WR_RH_PORTSTAT (RH_PS_OCIC); OK (0); + case (RH_C_PORT_RESET): + WR_RH_PORTSTAT (RH_PS_PRSC); OK (0); + } + break; + + case RH_SET_FEATURE | RH_OTHER | RH_CLASS: + switch (wValue) { + case (RH_PORT_SUSPEND): + WR_RH_PORTSTAT (RH_PS_PSS ); OK (0); + case (RH_PORT_RESET): /* BUG IN HUP CODE *********/ + if (RD_RH_PORTSTAT & RH_PS_CCS) + WR_RH_PORTSTAT (RH_PS_PRS); + OK (0); + case (RH_PORT_POWER): + WR_RH_PORTSTAT (RH_PS_PPS ); OK (0); + case (RH_PORT_ENABLE): /* BUG IN HUP CODE *********/ + if (RD_RH_PORTSTAT & RH_PS_CCS) + WR_RH_PORTSTAT (RH_PS_PES ); + OK (0); + } + break; + + case RH_SET_ADDRESS: gohci.rh.devnum = wValue; OK(0); + + case RH_GET_DESCRIPTOR: + switch ((wValue & 0xff00) >> 8) { + case (0x01): /* device descriptor */ + len = min_t(unsigned int, + leni, + min_t(unsigned int, + sizeof (root_hub_dev_des), + wLength)); + data_buf = root_hub_dev_des; OK(len); + case (0x02): /* configuration descriptor */ + len = min_t(unsigned int, + leni, + min_t(unsigned int, + sizeof (root_hub_config_des), + wLength)); + data_buf = root_hub_config_des; OK(len); + case (0x03): /* string descriptors */ + if(wValue==0x0300) { + len = min_t(unsigned int, + leni, + min_t(unsigned int, + sizeof (root_hub_str_index0), + wLength)); + data_buf = root_hub_str_index0; + OK(len); + } + if(wValue==0x0301) { + len = min_t(unsigned int, + leni, + min_t(unsigned int, + sizeof (root_hub_str_index1), + wLength)); + data_buf = root_hub_str_index1; + OK(len); + } + default: + stat = USB_ST_STALLED; + } + break; + + case RH_GET_DESCRIPTOR | RH_CLASS: + { + __u32 temp = roothub_a (&gohci); + + data_buf [0] = 9; /* min length; */ + data_buf [1] = 0x29; + data_buf [2] = temp & RH_A_NDP; + data_buf [3] = 0; + if (temp & RH_A_PSM) /* per-port power switching? */ + data_buf [3] |= 0x1; + if (temp & RH_A_NOCP) /* no overcurrent reporting? */ + data_buf [3] |= 0x10; + else if (temp & RH_A_OCPM) /* per-port overcurrent reporting? */ + data_buf [3] |= 0x8; + + /* corresponds to data_buf[4-7] */ + datab [1] = 0; + data_buf [5] = (temp & RH_A_POTPGT) >> 24; + temp = roothub_b (&gohci); + data_buf [7] = temp & RH_B_DR; + if (data_buf [2] < 7) { + data_buf [8] = 0xff; + } else { + data_buf [0] += 2; + data_buf [8] = (temp & RH_B_DR) >> 8; + data_buf [10] = data_buf [9] = 0xff; + } + + len = min_t(unsigned int, leni, + min_t(unsigned int, data_buf [0], wLength)); + OK (len); + } + + case RH_GET_CONFIGURATION: *(__u8 *) data_buf = 0x01; OK (1); + + case RH_SET_CONFIGURATION: WR_RH_STAT (0x10000); OK (0); + + default: + dbg ("unsupported root hub command"); + stat = USB_ST_STALLED; + } + +#ifdef DEBUG + ohci_dump_roothub (&gohci, 1); +#endif + + len = min_t(int, len, leni); + if (data != data_buf) + memcpy (data, data_buf, len); + dev->act_len = len; + dev->status = stat; + +#ifdef DEBUG + if (transfer_len) + urb_priv.actual_length = transfer_len; + pkt_print(dev, pipe, buffer, transfer_len, cmd, "RET(rh)", 0/*usb_pipein(pipe)*/); +#endif + + return stat; +} + +/*-------------------------------------------------------------------------*/ + +/* common code for handling submit messages - used for all but root hub */ +/* accesses. */ +int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, struct devrequest *setup, int interval) +{ + int stat = 0; + int maxsize = usb_maxpacket(dev, pipe); + int timeout; + + /* device pulled? Shortcut the action. */ + if (devgone == dev) { + dev->status = USB_ST_CRC_ERR; + return 0; + } + +#ifdef DEBUG + urb_priv.actual_length = 0; + pkt_print(dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe)); +#endif + if (!maxsize) { + err("submit_common_message: pipesize for pipe %lx is zero", + pipe); + return -1; + } + + if (sohci_submit_job(dev, pipe, buffer, transfer_len, setup, interval) < 0) { + err("sohci_submit_job failed"); + return -1; + } + + /* allow more time for a BULK device to react - some are slow */ +#define BULK_TO 5000 /* timeout in milliseconds */ + if (usb_pipetype (pipe) == PIPE_BULK) + timeout = BULK_TO; + else + timeout = 100; + + /* wait for it to complete */ + for (;;) { + /* check whether the controller is done */ + stat = hc_interrupt(); + if (stat < 0) { + stat = USB_ST_CRC_ERR; + break; + } + if (stat >= 0 && stat < 0xff) { + /* 0xff is returned for an SF-interrupt */ + break; + } + if (--timeout) { + wait_ms(1); + } else { + err("CTL:TIMEOUT "); + stat = USB_ST_CRC_ERR; + break; + } + } + /* we got an Root Hub Status Change interrupt */ + if (got_rhsc) { +#ifdef DEBUG + ohci_dump_roothub (&gohci, 1); +#endif + got_rhsc = 0; + /* abuse timeout */ + timeout = rh_check_port_status(&gohci); + if (timeout >= 0) { +#if 0 /* this does nothing useful, but leave it here in case that changes */ + /* the called routine adds 1 to the passed value */ + usb_hub_port_connect_change(gohci.rh.dev, timeout - 1); +#endif + /* + * XXX + * This is potentially dangerous because it assumes + * that only one device is ever plugged in! + */ + devgone = dev; + } + } + + dev->status = stat; + dev->act_len = transfer_len; + +#ifdef DEBUG + pkt_print(dev, pipe, buffer, transfer_len, setup, "RET(ctlr)", usb_pipein(pipe)); +#endif + + /* free TDs in urb_priv */ + urb_free_priv (&urb_priv); + return 0; +} + +/* submit routines called from usb.c */ +int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len) +{ + info("submit_bulk_msg"); + return submit_common_msg(dev, pipe, buffer, transfer_len, NULL, 0); +} + +int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, struct devrequest *setup) +{ + int maxsize = usb_maxpacket(dev, pipe); + + info("submit_control_msg"); +#ifdef DEBUG + urb_priv.actual_length = 0; + pkt_print(dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe)); +#endif + if (!maxsize) { + err("submit_control_message: pipesize for pipe %lx is zero", + pipe); + return -1; + } + if (((pipe >> 8) & 0x7f) == gohci.rh.devnum) { + gohci.rh.dev = dev; + /* root hub - redirect */ + return ohci_submit_rh_msg(dev, pipe, buffer, transfer_len, + setup); + } + + return submit_common_msg(dev, pipe, buffer, transfer_len, setup, 0); +} + +int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, int interval) +{ + info("submit_int_msg"); + return -1; +} + +/*-------------------------------------------------------------------------* + * HC functions + *-------------------------------------------------------------------------*/ + +/* reset the HC and BUS */ + +static int hc_reset (ohci_t *ohci) +{ + int timeout = 30; + int smm_timeout = 50; /* 0,5 sec */ + + if (readl (&ohci->regs->control) & OHCI_CTRL_IR) { /* SMM owns the HC */ + writel (OHCI_OCR, &ohci->regs->cmdstatus); /* request ownership */ + info("USB HC TakeOver from SMM"); + while (readl (&ohci->regs->control) & OHCI_CTRL_IR) { + wait_ms (10); + if (--smm_timeout == 0) { + err("USB HC TakeOver failed!"); + return -1; + } + } + } + + /* Disable HC interrupts */ + writel (OHCI_INTR_MIE, &ohci->regs->intrdisable); + + dbg("USB HC reset_hc usb-%s: ctrl = 0x%X ;", + ohci->slot_name, + readl (&ohci->regs->control)); + + /* Reset USB (needed by some controllers) */ + ohci->hc_control = 0; + writel (ohci->hc_control, &ohci->regs->control); + + /* HC Reset requires max 10 us delay */ + writel (OHCI_HCR, &ohci->regs->cmdstatus); + while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) { + if (--timeout == 0) { + err("USB HC reset timed out!"); + return -1; + } + udelay (1); + } + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* Start an OHCI controller, set the BUS operational + * enable interrupts + * connect the virtual root hub */ + +static int hc_start (ohci_t * ohci) +{ + __u32 mask; + unsigned int fminterval; + + ohci->disabled = 1; + + /* Tell the controller where the control and bulk lists are + * The lists are empty now. */ + + writel (0, &ohci->regs->ed_controlhead); + writel (0, &ohci->regs->ed_bulkhead); + + writel ((__u32)ohci->hcca, &ohci->regs->hcca); /* a reset clears this */ + + fminterval = 0x2edf; + writel ((fminterval * 9) / 10, &ohci->regs->periodicstart); + fminterval |= ((((fminterval - 210) * 6) / 7) << 16); + writel (fminterval, &ohci->regs->fminterval); + writel (0x628, &ohci->regs->lsthresh); + + /* start controller operations */ + ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; + ohci->disabled = 0; + writel (ohci->hc_control, &ohci->regs->control); + + /* disable all interrupts */ + mask = (OHCI_INTR_SO | OHCI_INTR_WDH | OHCI_INTR_SF | OHCI_INTR_RD | + OHCI_INTR_UE | OHCI_INTR_FNO | OHCI_INTR_RHSC | + OHCI_INTR_OC | OHCI_INTR_MIE); + writel (mask, &ohci->regs->intrdisable); + /* clear all interrupts */ + mask &= ~OHCI_INTR_MIE; + writel (mask, &ohci->regs->intrstatus); + /* Choose the interrupts we care about now - but w/o MIE */ + mask = OHCI_INTR_RHSC | OHCI_INTR_UE | OHCI_INTR_WDH | OHCI_INTR_SO; + writel (mask, &ohci->regs->intrenable); + +#ifdef OHCI_USE_NPS + /* required for AMD-756 and some Mac platforms */ + writel ((roothub_a (ohci) | RH_A_NPS) & ~RH_A_PSM, + &ohci->regs->roothub.a); + writel (RH_HS_LPSC, &ohci->regs->roothub.status); +#endif /* OHCI_USE_NPS */ + +#define mdelay(n) ({unsigned long msec=(n); while (msec--) udelay(1000);}) + /* POTPGT delay is bits 24-31, in 2 ms units. */ + mdelay ((roothub_a (ohci) >> 23) & 0x1fe); + + /* connect the virtual root hub */ + ohci->rh.devnum = 0; + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* an interrupt happens */ + +static int +hc_interrupt (void) +{ + ohci_t *ohci = &gohci; + struct ohci_regs *regs = ohci->regs; + int ints; + int stat = -1; + + if ((ohci->hcca->done_head != 0) && !(ohci_cpu_to_le32 (ohci->hcca->done_head) & 0x01)) { + ints = OHCI_INTR_WDH; + } else { + ints = readl (®s->intrstatus); + } + + /* dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no)); */ + + if (ints & OHCI_INTR_RHSC) { + got_rhsc = 1; + } + + if (ints & OHCI_INTR_UE) { + ohci->disabled++; + err ("OHCI Unrecoverable Error, controller usb-%s disabled", + ohci->slot_name); + /* e.g. due to PCI Master/Target Abort */ + +#ifdef DEBUG + ohci_dump (ohci, 1); +#endif + /* FIXME: be optimistic, hope that bug won't repeat often. */ + /* Make some non-interrupt context restart the controller. */ + /* Count and limit the retries though; either hardware or */ + /* software errors can go forever... */ + hc_reset (ohci); + return -1; + } + + if (ints & OHCI_INTR_WDH) { + writel (OHCI_INTR_WDH, ®s->intrdisable); + stat = dl_done_list (&gohci, dl_reverse_done_list (&gohci)); + writel (OHCI_INTR_WDH, ®s->intrenable); + } + + if (ints & OHCI_INTR_SO) { + dbg("USB Schedule overrun\n"); + writel (OHCI_INTR_SO, ®s->intrenable); + stat = -1; + } + + /* FIXME: this assumes SOF (1/ms) interrupts don't get lost... */ + if (ints & OHCI_INTR_SF) { + unsigned int frame = ohci_cpu_to_le16 (ohci->hcca->frame_no) & 1; + writel (OHCI_INTR_SF, ®s->intrdisable); + if (ohci->ed_rm_list[frame] != NULL) + writel (OHCI_INTR_SF, ®s->intrenable); + stat = 0xff; + } + + writel (ints, ®s->intrstatus); + return stat; +} + +/*-------------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------------*/ + +/* De-allocate all resources.. */ + +static void hc_release_ohci (ohci_t *ohci) +{ + dbg ("USB HC release ohci usb-%s", ohci->slot_name); + + if (!ohci->disabled) + hc_reset (ohci); +} + +/*-------------------------------------------------------------------------*/ + +/* + * low level initalisation routine, called from usb.c + */ +static char ohci_inited = 0; + +int usb_lowlevel_init(void) +{ + + /* Set the USB Clock */ + *(vu_long *)MPC5XXX_CDM_48_FDC = 0x0001bbbb; + *(vu_long *)MPC5XXX_GPS_PORT_CONFIG &= ~0x00800000; + /* Activate USB port */ + *(vu_long *)MPC5XXX_GPS_PORT_CONFIG |= 0x00001000; + + memset (&gohci, 0, sizeof (ohci_t)); + memset (&urb_priv, 0, sizeof (urb_priv_t)); + + /* align the storage */ + if ((__u32)&ghcca[0] & 0xff) { + err("HCCA not aligned!!"); + return -1; + } + phcca = &ghcca[0]; + info("aligned ghcca %p", phcca); + memset(&ohci_dev, 0, sizeof(struct ohci_device)); + if ((__u32)&ohci_dev.ed[0] & 0x7) { + err("EDs not aligned!!"); + return -1; + } + memset(gtd, 0, sizeof(td_t) * (NUM_TD + 1)); + if ((__u32)gtd & 0x7) { + err("TDs not aligned!!"); + return -1; + } + ptd = gtd; + gohci.hcca = phcca; + memset (phcca, 0, sizeof (struct ohci_hcca)); + + gohci.disabled = 1; + gohci.sleeping = 0; + gohci.irq = -1; + gohci.regs = (struct ohci_regs *)MPC5XXX_USB; + + gohci.flags = 0; + gohci.slot_name = "mpc5200"; + + if (hc_reset (&gohci) < 0) { + hc_release_ohci (&gohci); + return -1; + } + + if (hc_start (&gohci) < 0) { + err ("can't start usb-%s", gohci.slot_name); + hc_release_ohci (&gohci); + return -1; + } + +#ifdef DEBUG + ohci_dump (&gohci, 1); +#endif + ohci_inited = 1; + return 0; +} + +int usb_lowlevel_stop(void) +{ + /* this gets called really early - before the controller has */ + /* even been initialized! */ + if (!ohci_inited) + return 0; + /* TODO release any interrupts, etc. */ + /* call hc_release_ohci() here ? */ + hc_reset (&gohci); + return 0; +} + +#endif /* CONFIG_USB_OHCI */ diff --git a/cpu/mpc5xxx/usb_ohci.h b/cpu/mpc5xxx/usb_ohci.h new file mode 100644 index 000000000..11b361af0 --- /dev/null +++ b/cpu/mpc5xxx/usb_ohci.h @@ -0,0 +1,424 @@ +/* + * URB OHCI HCD (Host Controller Driver) for USB. + * + * (C) Copyright 1999 Roman Weissgaerber + * (C) Copyright 2000-2001 David Brownell + * + * usb-ohci.h + */ + + +static int cc_to_error[16] = { + +/* mapping of the OHCI CC status to error codes */ + /* No Error */ 0, + /* CRC Error */ USB_ST_CRC_ERR, + /* Bit Stuff */ USB_ST_BIT_ERR, + /* Data Togg */ USB_ST_CRC_ERR, + /* Stall */ USB_ST_STALLED, + /* DevNotResp */ -1, + /* PIDCheck */ USB_ST_BIT_ERR, + /* UnExpPID */ USB_ST_BIT_ERR, + /* DataOver */ USB_ST_BUF_ERR, + /* DataUnder */ USB_ST_BUF_ERR, + /* reservd */ -1, + /* reservd */ -1, + /* BufferOver */ USB_ST_BUF_ERR, + /* BuffUnder */ USB_ST_BUF_ERR, + /* Not Access */ -1, + /* Not Access */ -1 +}; + +/* ED States */ + +#define ED_NEW 0x00 +#define ED_UNLINK 0x01 +#define ED_OPER 0x02 +#define ED_DEL 0x04 +#define ED_URB_DEL 0x08 + +/* usb_ohci_ed */ +struct ed { + __u32 hwINFO; + __u32 hwTailP; + __u32 hwHeadP; + __u32 hwNextED; + + struct ed *ed_prev; + __u8 int_period; + __u8 int_branch; + __u8 int_load; + __u8 int_interval; + __u8 state; + __u8 type; + __u16 last_iso; + struct ed *ed_rm_list; + + struct usb_device *usb_dev; + __u32 unused[3]; +} __attribute((aligned(16))); +typedef struct ed ed_t; + + +/* TD info field */ +#define TD_CC 0xf0000000 +#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f) +#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28) +#define TD_EC 0x0C000000 +#define TD_T 0x03000000 +#define TD_T_DATA0 0x02000000 +#define TD_T_DATA1 0x03000000 +#define TD_T_TOGGLE 0x00000000 +#define TD_R 0x00040000 +#define TD_DI 0x00E00000 +#define TD_DI_SET(X) (((X) & 0x07)<< 21) +#define TD_DP 0x00180000 +#define TD_DP_SETUP 0x00000000 +#define TD_DP_IN 0x00100000 +#define TD_DP_OUT 0x00080000 + +#define TD_ISO 0x00010000 +#define TD_DEL 0x00020000 + +/* CC Codes */ +#define TD_CC_NOERROR 0x00 +#define TD_CC_CRC 0x01 +#define TD_CC_BITSTUFFING 0x02 +#define TD_CC_DATATOGGLEM 0x03 +#define TD_CC_STALL 0x04 +#define TD_DEVNOTRESP 0x05 +#define TD_PIDCHECKFAIL 0x06 +#define TD_UNEXPECTEDPID 0x07 +#define TD_DATAOVERRUN 0x08 +#define TD_DATAUNDERRUN 0x09 +#define TD_BUFFEROVERRUN 0x0C +#define TD_BUFFERUNDERRUN 0x0D +#define TD_NOTACCESSED 0x0F + + +#define MAXPSW 1 + +struct td { + __u32 hwINFO; + __u32 hwCBP; /* Current Buffer Pointer */ + __u32 hwNextTD; /* Next TD Pointer */ + __u32 hwBE; /* Memory Buffer End Pointer */ + + __u16 hwPSW[MAXPSW]; + __u8 unused; + __u8 index; + struct ed *ed; + struct td *next_dl_td; + struct usb_device *usb_dev; + int transfer_len; + __u32 data; + + __u32 unused2[2]; +} __attribute((aligned(32))); +typedef struct td td_t; + +#define OHCI_ED_SKIP (1 << 14) + +/* + * The HCCA (Host Controller Communications Area) is a 256 byte + * structure defined in the OHCI spec. that the host controller is + * told the base address of. It must be 256-byte aligned. + */ + +#define NUM_INTS 32 /* part of the OHCI standard */ +struct ohci_hcca { + __u32 int_table[NUM_INTS]; /* Interrupt ED table */ +#if defined(CONFIG_MPC5200) + __u16 pad1; /* set to 0 on each frame_no change */ + __u16 frame_no; /* current frame number */ +#else + __u16 frame_no; /* current frame number */ + __u16 pad1; /* set to 0 on each frame_no change */ +#endif + __u32 done_head; /* info returned for an interrupt */ + u8 reserved_for_hc[116]; +} __attribute((aligned(256))); + + +/* + * Maximum number of root hub ports. + */ +#define MAX_ROOT_PORTS 15 /* maximum OHCI root hub ports */ + +/* + * This is the structure of the OHCI controller's memory mapped I/O + * region. This is Memory Mapped I/O. You must use the readl() and + * writel() macros defined in asm/io.h to access these!! + */ +struct ohci_regs { + /* control and status registers */ + __u32 revision; + __u32 control; + __u32 cmdstatus; + __u32 intrstatus; + __u32 intrenable; + __u32 intrdisable; + /* memory pointers */ + __u32 hcca; + __u32 ed_periodcurrent; + __u32 ed_controlhead; + __u32 ed_controlcurrent; + __u32 ed_bulkhead; + __u32 ed_bulkcurrent; + __u32 donehead; + /* frame counters */ + __u32 fminterval; + __u32 fmremaining; + __u32 fmnumber; + __u32 periodicstart; + __u32 lsthresh; + /* Root hub ports */ + struct ohci_roothub_regs { + __u32 a; + __u32 b; + __u32 status; + __u32 portstatus[MAX_ROOT_PORTS]; + } roothub; +} __attribute((aligned(32))); + + +/* OHCI CONTROL AND STATUS REGISTER MASKS */ + +/* + * HcControl (control) register masks + */ +#define OHCI_CTRL_CBSR (3 << 0) /* control/bulk service ratio */ +#define OHCI_CTRL_PLE (1 << 2) /* periodic list enable */ +#define OHCI_CTRL_IE (1 << 3) /* isochronous enable */ +#define OHCI_CTRL_CLE (1 << 4) /* control list enable */ +#define OHCI_CTRL_BLE (1 << 5) /* bulk list enable */ +#define OHCI_CTRL_HCFS (3 << 6) /* host controller functional state */ +#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */ +#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */ +#define OHCI_CTRL_RWE (1 << 10) /* remote wakeup enable */ + +/* pre-shifted values for HCFS */ +# define OHCI_USB_RESET (0 << 6) +# define OHCI_USB_RESUME (1 << 6) +# define OHCI_USB_OPER (2 << 6) +# define OHCI_USB_SUSPEND (3 << 6) + +/* + * HcCommandStatus (cmdstatus) register masks + */ +#define OHCI_HCR (1 << 0) /* host controller reset */ +#define OHCI_CLF (1 << 1) /* control list filled */ +#define OHCI_BLF (1 << 2) /* bulk list filled */ +#define OHCI_OCR (1 << 3) /* ownership change request */ +#define OHCI_SOC (3 << 16) /* scheduling overrun count */ + +/* + * masks used with interrupt registers: + * HcInterruptStatus (intrstatus) + * HcInterruptEnable (intrenable) + * HcInterruptDisable (intrdisable) + */ +#define OHCI_INTR_SO (1 << 0) /* scheduling overrun */ +#define OHCI_INTR_WDH (1 << 1) /* writeback of done_head */ +#define OHCI_INTR_SF (1 << 2) /* start frame */ +#define OHCI_INTR_RD (1 << 3) /* resume detect */ +#define OHCI_INTR_UE (1 << 4) /* unrecoverable error */ +#define OHCI_INTR_FNO (1 << 5) /* frame number overflow */ +#define OHCI_INTR_RHSC (1 << 6) /* root hub status change */ +#define OHCI_INTR_OC (1 << 30) /* ownership change */ +#define OHCI_INTR_MIE (1 << 31) /* master interrupt enable */ + + +/* Virtual Root HUB */ +struct virt_root_hub { + int devnum; /* Address of Root Hub endpoint */ + void *dev; /* was urb */ + void *int_addr; + int send; + int interval; +}; + +/* USB HUB CONSTANTS (not OHCI-specific; see hub.h) */ + +/* destination of request */ +#define RH_INTERFACE 0x01 +#define RH_ENDPOINT 0x02 +#define RH_OTHER 0x03 + +#define RH_CLASS 0x20 +#define RH_VENDOR 0x40 + +/* Requests: bRequest << 8 | bmRequestType */ +#define RH_GET_STATUS 0x0080 +#define RH_CLEAR_FEATURE 0x0100 +#define RH_SET_FEATURE 0x0300 +#define RH_SET_ADDRESS 0x0500 +#define RH_GET_DESCRIPTOR 0x0680 +#define RH_SET_DESCRIPTOR 0x0700 +#define RH_GET_CONFIGURATION 0x0880 +#define RH_SET_CONFIGURATION 0x0900 +#define RH_GET_STATE 0x0280 +#define RH_GET_INTERFACE 0x0A80 +#define RH_SET_INTERFACE 0x0B00 +#define RH_SYNC_FRAME 0x0C80 +/* Our Vendor Specific Request */ +#define RH_SET_EP 0x2000 + + +/* Hub port features */ +#define RH_PORT_CONNECTION 0x00 +#define RH_PORT_ENABLE 0x01 +#define RH_PORT_SUSPEND 0x02 +#define RH_PORT_OVER_CURRENT 0x03 +#define RH_PORT_RESET 0x04 +#define RH_PORT_POWER 0x08 +#define RH_PORT_LOW_SPEED 0x09 + +#define RH_C_PORT_CONNECTION 0x10 +#define RH_C_PORT_ENABLE 0x11 +#define RH_C_PORT_SUSPEND 0x12 +#define RH_C_PORT_OVER_CURRENT 0x13 +#define RH_C_PORT_RESET 0x14 + +/* Hub features */ +#define RH_C_HUB_LOCAL_POWER 0x00 +#define RH_C_HUB_OVER_CURRENT 0x01 + +#define RH_DEVICE_REMOTE_WAKEUP 0x00 +#define RH_ENDPOINT_STALL 0x01 + +#define RH_ACK 0x01 +#define RH_REQ_ERR -1 +#define RH_NACK 0x00 + + +/* OHCI ROOT HUB REGISTER MASKS */ + +/* roothub.portstatus [i] bits */ +#define RH_PS_CCS 0x00000001 /* current connect status */ +#define RH_PS_PES 0x00000002 /* port enable status*/ +#define RH_PS_PSS 0x00000004 /* port suspend status */ +#define RH_PS_POCI 0x00000008 /* port over current indicator */ +#define RH_PS_PRS 0x00000010 /* port reset status */ +#define RH_PS_PPS 0x00000100 /* port power status */ +#define RH_PS_LSDA 0x00000200 /* low speed device attached */ +#define RH_PS_CSC 0x00010000 /* connect status change */ +#define RH_PS_PESC 0x00020000 /* port enable status change */ +#define RH_PS_PSSC 0x00040000 /* port suspend status change */ +#define RH_PS_OCIC 0x00080000 /* over current indicator change */ +#define RH_PS_PRSC 0x00100000 /* port reset status change */ + +/* roothub.status bits */ +#define RH_HS_LPS 0x00000001 /* local power status */ +#define RH_HS_OCI 0x00000002 /* over current indicator */ +#define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */ +#define RH_HS_LPSC 0x00010000 /* local power status change */ +#define RH_HS_OCIC 0x00020000 /* over current indicator change */ +#define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */ + +/* roothub.b masks */ +#define RH_B_DR 0x0000ffff /* device removable flags */ +#define RH_B_PPCM 0xffff0000 /* port power control mask */ + +/* roothub.a masks */ +#define RH_A_NDP (0xff << 0) /* number of downstream ports */ +#define RH_A_PSM (1 << 8) /* power switching mode */ +#define RH_A_NPS (1 << 9) /* no power switching */ +#define RH_A_DT (1 << 10) /* device type (mbz) */ +#define RH_A_OCPM (1 << 11) /* over current protection mode */ +#define RH_A_NOCP (1 << 12) /* no over current protection */ +#define RH_A_POTPGT (0xff << 24) /* power on to power good time */ + +/* urb */ +#define N_URB_TD 48 +typedef struct +{ + ed_t *ed; + __u16 length; /* number of tds associated with this request */ + __u16 td_cnt; /* number of tds already serviced */ + int state; + unsigned long pipe; + int actual_length; + td_t *td[N_URB_TD]; /* list pointer to all corresponding TDs associated with this request */ +} urb_priv_t; +#define URB_DEL 1 + +/* + * This is the full ohci controller description + * + * Note how the "proper" USB information is just + * a subset of what the full implementation needs. (Linus) + */ + + +typedef struct ohci { + struct ohci_hcca *hcca; /* hcca */ + /*dma_addr_t hcca_dma;*/ + + int irq; + int disabled; /* e.g. got a UE, we're hung */ + int sleeping; + unsigned long flags; /* for HC bugs */ + + struct ohci_regs *regs; /* OHCI controller's memory */ + + ed_t *ed_rm_list[2]; /* lists of all endpoints to be removed */ + ed_t *ed_bulktail; /* last endpoint of bulk list */ + ed_t *ed_controltail; /* last endpoint of control list */ + int intrstatus; + __u32 hc_control; /* copy of the hc control reg */ + struct usb_device *dev[32]; + struct virt_root_hub rh; + + const char *slot_name; +} ohci_t; + +#define NUM_EDS 8 /* num of preallocated endpoint descriptors */ + +struct ohci_device { + ed_t ed[NUM_EDS]; + int ed_cnt; +}; + +/* hcd */ +/* endpoint */ +static int ep_link(ohci_t * ohci, ed_t * ed); +static int ep_unlink(ohci_t * ohci, ed_t * ed); +static ed_t * ep_add_ed(struct usb_device * usb_dev, unsigned long pipe); + +/*-------------------------------------------------------------------------*/ + +/* we need more TDs than EDs */ +#define NUM_TD 64 + +/* +1 so we can align the storage */ +td_t gtd[NUM_TD+1]; +/* pointers to aligned storage */ +td_t *ptd; + +/* TDs ... */ +static inline struct td * +td_alloc (struct usb_device *usb_dev) +{ + int i; + struct td *td; + + td = NULL; + for (i = 0; i < NUM_TD; i++) + { + if (ptd[i].usb_dev == NULL) + { + td = &ptd[i]; + td->usb_dev = usb_dev; + break; + } + } + + return td; +} + +static inline void +ed_free (struct ed *ed) +{ + ed->usb_dev = NULL; +} diff --git a/doc/README.ns9750dev b/doc/README.ns9750dev new file mode 100644 index 000000000..29914406b --- /dev/null +++ b/doc/README.ns9750dev @@ -0,0 +1,36 @@ +U-Boot Port to the NS9750 DevKit from NetSilicon + +1 Overview +2 Board Configuration +3 Installation + + +1 Overview +---------- + +This port supports these NS9750 features. + +o one UART + +2 Board Configuration +--------------------- + +Switches: +SW10: 4 +SW11: 6,7 +SW16: 6,7,8 +SW17-SW20: 1 +SW4: 3, 6 +SW 1: 1 +SW2: 4 +SW3: 3 +SW8: 3 (rotated by 180 degree!!!!) + +Serial Console is Port B (bottom right port) + +3 Installation +-------------- + +Have fun, +-- +Markus Pietrek diff --git a/drivers/ns9750_eth.c b/drivers/ns9750_eth.c new file mode 100644 index 000000000..067ff8efa --- /dev/null +++ b/drivers/ns9750_eth.c @@ -0,0 +1,797 @@ +/*********************************************************************** + * + * Copyright (C) 2004 by FS Forth-Systeme GmbH. + * All rights reserved. + * + * $Id: ns9750_eth.c,v 1.2 2004/02/24 14:09:39 mpietrek Exp $ + * @Author: Markus Pietrek + * @Descr: Ethernet driver for the NS9750. Uses DMA Engine with polling + * interrupt status. But interrupts are not enabled. + * Only one tx buffer descriptor and the RXA buffer descriptor are used + * Currently no transmit lockup handling is included. eth_send has a 5s + * timeout for sending frames. No retransmits are performed when an + * error occurs. + * @References: [1] NS9750 Hardware Reference, December 2003 + * [2] Intel LXT971 Datasheet #249414 Rev. 02 + * [3] NS7520 Linux Ethernet Driver + * + * 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 /* NetSendPacket */ + +#include "ns9750_eth.h" /* for Ethernet and PHY */ + +#ifdef CONFIG_DRIVER_NS9750_ETHERNET + +/* some definition to make transistion to linux easier */ + +#define NS9750_DRIVER_NAME "eth" +#define KERN_WARNING "Warning:" +#define KERN_ERR "Error:" +#define KERN_INFO "Info:" + +#if 0 +# define DEBUG +#endif + +#ifdef DEBUG +# define printk printf + +# define DEBUG_INIT 0x0001 +# define DEBUG_MINOR 0x0002 +# define DEBUG_RX 0x0004 +# define DEBUG_TX 0x0008 +# define DEBUG_INT 0x0010 +# define DEBUG_POLL 0x0020 +# define DEBUG_LINK 0x0040 +# define DEBUG_MII 0x0100 +# define DEBUG_MII_LOW 0x0200 +# define DEBUG_MEM 0x0400 +# define DEBUG_ERROR 0x4000 +# define DEBUG_ERROR_CRIT 0x8000 + +static int nDebugLvl = DEBUG_ERROR_CRIT; + +# define DEBUG_ARGS0( FLG, a0 ) if( ( nDebugLvl & (FLG) ) == (FLG) ) \ + printf("%s: " a0, __FUNCTION__, 0, 0, 0, 0, 0, 0 ) +# define DEBUG_ARGS1( FLG, a0, a1 ) if( ( nDebugLvl & (FLG) ) == (FLG)) \ + printf("%s: " a0, __FUNCTION__, (int)(a1), 0, 0, 0, 0, 0 ) +# define DEBUG_ARGS2( FLG, a0, a1, a2 ) if( (nDebugLvl & (FLG)) ==(FLG))\ + printf("%s: " a0, __FUNCTION__, (int)(a1), (int)(a2), 0, 0,0,0 ) +# define DEBUG_ARGS3( FLG, a0, a1, a2, a3 ) if((nDebugLvl &(FLG))==(FLG))\ + printf("%s: "a0,__FUNCTION__,(int)(a1),(int)(a2),(int)(a3),0,0,0) +# define DEBUG_FN( FLG ) if( (nDebugLvl & (FLG)) == (FLG) ) \ + printf("\r%s:line %d\n", (int)__FUNCTION__, __LINE__, 0,0,0,0); +# define ASSERT( expr, func ) if( !( expr ) ) { \ + printf( "Assertion failed! %s:line %d %s\n", \ + (int)__FUNCTION__,__LINE__,(int)(#expr),0,0,0); \ + func } +#else /* DEBUG */ +# define printk(...) +# define DEBUG_ARGS0( FLG, a0 ) +# define DEBUG_ARGS1( FLG, a0, a1 ) +# define DEBUG_ARGS2( FLG, a0, a1, a2 ) +# define DEBUG_ARGS3( FLG, a0, a1, a2, a3 ) +# define DEBUG_FN( n ) +# define ASSERT(expr, func) +#endif /* DEBUG */ + +#define NS9750_MII_NEG_DELAY (5*CFG_HZ) /* in s */ +#define TX_TIMEOUT (5*CFG_HZ) /* in s */ + +/* @TODO move it to eeprom.h */ +#define FS_EEPROM_AUTONEG_MASK 0x7 +#define FS_EEPROM_AUTONEG_SPEED_MASK 0x1 +#define FS_EEPROM_AUTONEG_SPEED_10 0x0 +#define FS_EEPROM_AUTONEG_SPEED_100 0x1 +#define FS_EEPROM_AUTONEG_DUPLEX_MASK 0x2 +#define FS_EEPROM_AUTONEG_DUPLEX_HALF 0x0 +#define FS_EEPROM_AUTONEG_DUPLEX_FULL 0x2 +#define FS_EEPROM_AUTONEG_ENABLE_MASK 0x4 +#define FS_EEPROM_AUTONEG_DISABLE 0x0 +#define FS_EEPROM_AUTONEG_ENABLE 0x4 + +/* buffer descriptors taken from [1] p.306 */ +typedef struct +{ + unsigned int* punSrc; + unsigned int unLen; /* 11 bits */ + unsigned int* punDest; /* unused */ + union { + unsigned int unReg; + struct { + unsigned uStatus : 16; + unsigned uRes : 12; + unsigned uFull : 1; + unsigned uEnable : 1; + unsigned uInt : 1; + unsigned uWrap : 1; + } bits; + } s; +} rx_buffer_desc_t; + +typedef struct +{ + unsigned int* punSrc; + unsigned int unLen; /* 10 bits */ + unsigned int* punDest; /* unused */ + union { + unsigned int unReg; /* only 32bit accesses may done to NS9750 + * eth engine */ + struct { + unsigned uStatus : 16; + unsigned uRes : 12; + unsigned uFull : 1; + unsigned uLast : 1; + unsigned uInt : 1; + unsigned uWrap : 1; + } bits; + } s; +} tx_buffer_desc_t; + +static int ns9750_eth_reset( void ); + +static void ns9750_link_force( void ); +static void ns9750_link_auto_negotiate( void ); +static void ns9750_link_update_egcr( void ); +static void ns9750_link_print_changed( void ); + +/* the PHY stuff */ + +static char ns9750_mii_identify_phy( void ); +static unsigned short ns9750_mii_read( unsigned short uiRegister ); +static void ns9750_mii_write( unsigned short uiRegister, unsigned short uiData ); +static unsigned int ns9750_mii_get_clock_divisor( unsigned int unMaxMDIOClk ); +static unsigned int ns9750_mii_poll_busy( void ); + +static unsigned int nPhyMaxMdioClock = PHY_MDIO_MAX_CLK; +static unsigned char ucLinkMode = FS_EEPROM_AUTONEG_ENABLE; +static unsigned int uiLastLinkStatus; +static PhyType phyDetected = PHY_NONE; + +/* we use only one tx buffer descriptor */ +static tx_buffer_desc_t* pTxBufferDesc = + (tx_buffer_desc_t*) get_eth_reg_addr( NS9750_ETH_TXBD ); + +/* we use only one rx buffer descriptor of the 4 */ +static rx_buffer_desc_t aRxBufferDesc[ 4 ]; + +/*********************************************************************** + * @Function: eth_init + * @Return: -1 on failure otherwise 0 + * @Descr: Initializes the ethernet engine and uses either FS Forth's default + * MAC addr or the one in environment + ***********************************************************************/ + +int eth_init (bd_t * pbis) +{ + /* This default MAC Addr is reserved by FS Forth-Systeme for the case of + EEPROM failures */ + unsigned char aucMACAddr[6] = { 0x00, 0x04, 0xf3, 0x00, 0x06, 0x35 }; + char *pcTmp = getenv ("ethaddr"); + char *pcEnd; + int i; + + DEBUG_FN (DEBUG_INIT); + + /* no need to check for hardware */ + + if (!ns9750_eth_reset ()) + return -1; + + if (pcTmp != NULL) + for (i = 0; i < 6; i++) { + aucMACAddr[i] = + pcTmp ? simple_strtoul (pcTmp, &pcEnd, + 16) : 0; + pcTmp = (*pcTmp) ? pcEnd + 1 : pcEnd; + } + + /* configure ethernet address */ + + *get_eth_reg_addr (NS9750_ETH_SA1) = + aucMACAddr[5] << 8 | aucMACAddr[4]; + *get_eth_reg_addr (NS9750_ETH_SA2) = + aucMACAddr[3] << 8 | aucMACAddr[2]; + *get_eth_reg_addr (NS9750_ETH_SA3) = + aucMACAddr[1] << 8 | aucMACAddr[0]; + + /* enable hardware */ + + *get_eth_reg_addr (NS9750_ETH_MAC1) = NS9750_ETH_MAC1_RXEN; + + /* the linux kernel may give packets < 60 bytes, for example arp */ + *get_eth_reg_addr (NS9750_ETH_MAC2) = NS9750_ETH_MAC2_CRCEN | + NS9750_ETH_MAC2_PADEN | NS9750_ETH_MAC2_HUGE; + + /* enable receive and transmit FIFO, use 10/100 Mbps MII */ + *get_eth_reg_addr (NS9750_ETH_EGCR1) = + NS9750_ETH_EGCR1_ETXWM | + NS9750_ETH_EGCR1_ERX | + NS9750_ETH_EGCR1_ERXDMA | + NS9750_ETH_EGCR1_ETX | + NS9750_ETH_EGCR1_ETXDMA | NS9750_ETH_EGCR1_ITXA; + + /* prepare DMA descriptors */ + for (i = 0; i < 4; i++) { + aRxBufferDesc[i].punSrc = 0; + aRxBufferDesc[i].unLen = 0; + aRxBufferDesc[i].s.bits.uWrap = 1; + aRxBufferDesc[i].s.bits.uInt = 1; + aRxBufferDesc[i].s.bits.uEnable = 0; + aRxBufferDesc[i].s.bits.uFull = 0; + } + + /* NetRxPackets[ 0 ] is initialized before eth_init is called and never + changes. NetRxPackets is 32bit aligned */ + aRxBufferDesc[0].punSrc = (unsigned int *) NetRxPackets[0]; + aRxBufferDesc[0].s.bits.uEnable = 1; + aRxBufferDesc[0].unLen = 1522; /* as stated in [1] p.307 */ + + *get_eth_reg_addr (NS9750_ETH_RXAPTR) = + (unsigned int) &aRxBufferDesc[0]; + + /* [1] Tab. 221 states less than 5us */ + *get_eth_reg_addr (NS9750_ETH_EGCR1) |= NS9750_ETH_EGCR1_ERXINIT; + while (! + (*get_eth_reg_addr (NS9750_ETH_EGSR) & NS9750_ETH_EGSR_RXINIT)) + /* wait for finish */ + udelay (1); + + /* @TODO do we need to clear RXINIT? */ + *get_eth_reg_addr (NS9750_ETH_EGCR1) &= ~NS9750_ETH_EGCR1_ERXINIT; + + *get_eth_reg_addr (NS9750_ETH_RXFREE) = 0x1; + + return 0; +} + +/*********************************************************************** + * @Function: eth_send + * @Return: -1 on timeout otherwise 1 + * @Descr: sends one frame by DMA + ***********************************************************************/ + +int eth_send (volatile void *pPacket, int nLen) +{ + ulong ulTimeout; + + DEBUG_FN (DEBUG_TX); + + /* clear old status values */ + *get_eth_reg_addr (NS9750_ETH_EINTR) &= + *get_eth_reg_addr (NS9750_ETH_EINTR) & NS9750_ETH_EINTR_TX_MA; + + /* prepare Tx Descriptors */ + + pTxBufferDesc->punSrc = (unsigned int *) pPacket; /* pPacket is 32bit + * aligned */ + pTxBufferDesc->unLen = nLen; + /* only 32bit accesses allowed. wrap, full, interrupt and enabled to 1 */ + pTxBufferDesc->s.unReg = 0xf0000000; + /* pTxBufferDesc is the first possible buffer descriptor */ + *get_eth_reg_addr (NS9750_ETH_TXPTR) = 0x0; + + /* enable processor for next frame */ + + *get_eth_reg_addr (NS9750_ETH_EGCR2) &= ~NS9750_ETH_EGCR2_TCLER; + *get_eth_reg_addr (NS9750_ETH_EGCR2) |= NS9750_ETH_EGCR2_TCLER; + + ulTimeout = get_timer (0); + + DEBUG_ARGS0 (DEBUG_TX | DEBUG_MINOR, + "Waiting for transmission to finish\n"); + while (! + (*get_eth_reg_addr (NS9750_ETH_EINTR) & + (NS9750_ETH_EINTR_TXDONE | NS9750_ETH_EINTR_TXERR))) { + /* do nothing, wait for completion */ + if (get_timer (0) - ulTimeout > TX_TIMEOUT) { + DEBUG_ARGS0 (DEBUG_TX, "Transmit Timed out\n"); + return -1; + } + } + DEBUG_ARGS0 (DEBUG_TX | DEBUG_MINOR, "transmitted...\n"); + + return 0; +} + +/*********************************************************************** + * @Function: eth_rx + * @Return: size of last frame in bytes or 0 if no frame available + * @Descr: gives one frame to U-Boot which has been copied by DMA engine already + * to NetRxPackets[ 0 ]. + ***********************************************************************/ + +int eth_rx (void) +{ + int nLen = 0; + unsigned int unStatus; + + unStatus = + *get_eth_reg_addr (NS9750_ETH_EINTR) & NS9750_ETH_EINTR_RX_MA; + + if (!unStatus) + /* no packet available, return immediately */ + return 0; + + DEBUG_FN (DEBUG_RX); + + /* unLen always < max(nLen) and discard checksum */ + nLen = (int) aRxBufferDesc[0].unLen - 4; + + /* acknowledge status register */ + *get_eth_reg_addr (NS9750_ETH_EINTR) = unStatus; + + aRxBufferDesc[0].unLen = 1522; + aRxBufferDesc[0].s.bits.uFull = 0; + + /* Buffer A descriptor available again */ + *get_eth_reg_addr (NS9750_ETH_RXFREE) |= 0x1; + + /* NetReceive may call eth_send. Due to a possible bug of the NS9750 we + * have to acknowledge the received frame before sending a new one */ + if (unStatus & NS9750_ETH_EINTR_RXDONEA) + NetReceive (NetRxPackets[0], nLen); + + return nLen; +} + +/*********************************************************************** + * @Function: eth_halt + * @Return: n/a + * @Descr: stops the ethernet engine + ***********************************************************************/ + +void eth_halt (void) +{ + DEBUG_FN (DEBUG_INIT); + + *get_eth_reg_addr (NS9750_ETH_MAC1) &= ~NS9750_ETH_MAC1_RXEN; + *get_eth_reg_addr (NS9750_ETH_EGCR1) &= ~(NS9750_ETH_EGCR1_ERX | + NS9750_ETH_EGCR1_ERXDMA | + NS9750_ETH_EGCR1_ETX | + NS9750_ETH_EGCR1_ETXDMA); +} + +/*********************************************************************** + * @Function: ns9750_eth_reset + * @Return: 0 on failure otherwise 1 + * @Descr: resets the ethernet interface and the PHY, + * performs auto negotiation or fixed modes + ***********************************************************************/ + +static int ns9750_eth_reset (void) +{ + DEBUG_FN (DEBUG_MINOR); + + /* Reset MAC */ + *get_eth_reg_addr (NS9750_ETH_EGCR1) |= NS9750_ETH_EGCR1_MAC_HRST; + udelay (5); /* according to [1], p.322 */ + *get_eth_reg_addr (NS9750_ETH_EGCR1) &= ~NS9750_ETH_EGCR1_MAC_HRST; + + /* reset and initialize PHY */ + + *get_eth_reg_addr (NS9750_ETH_MAC1) &= ~NS9750_ETH_MAC1_SRST; + + /* we don't support hot plugging of PHY, therefore we don't reset + phyDetected and nPhyMaxMdioClock here. The risk is if the setting is + incorrect the first open + may detect the PHY correctly but succeding will fail + For reseting the PHY and identifying we have to use the standard + MDIO CLOCK value 2.5 MHz only after hardware reset + After having identified the PHY we will do faster */ + + *get_eth_reg_addr (NS9750_ETH_MCFG) = + ns9750_mii_get_clock_divisor (nPhyMaxMdioClock); + + /* reset PHY */ + ns9750_mii_write (PHY_COMMON_CTRL, PHY_COMMON_CTRL_RESET); + ns9750_mii_write (PHY_COMMON_CTRL, 0); + + /* @TODO check time */ + udelay (3000); /* [2] p.70 says at least 300us reset recovery time. But + go sure, it didn't worked stable at higher timer + frequencies under LxNETES-2.x */ + + /* MII clock has been setup to default, ns9750_mii_identify_phy should + work for all */ + + if (!ns9750_mii_identify_phy ()) { + printk (KERN_ERR NS9750_DRIVER_NAME + ": Unsupported PHY, aborting\n"); + return 0; + } + + /* now take the highest MDIO clock possible after detection */ + *get_eth_reg_addr (NS9750_ETH_MCFG) = + ns9750_mii_get_clock_divisor (nPhyMaxMdioClock); + + + /* PHY has been detected, so there can be no abort reason and we can + finish initializing ethernet */ + + uiLastLinkStatus = 0xff; /* undefined */ + + if ((ucLinkMode & FS_EEPROM_AUTONEG_ENABLE_MASK) == + FS_EEPROM_AUTONEG_DISABLE) + /* use parameters defined */ + ns9750_link_force (); + else + ns9750_link_auto_negotiate (); + + if (phyDetected == PHY_LXT971A) + /* set LED2 to link mode */ + ns9750_mii_write (PHY_LXT971_LED_CFG, + PHY_LXT971_LED_CFG_LINK_ACT << + PHY_LXT971_LED_CFG_SHIFT_LED2); + + return 1; +} + +/*********************************************************************** + * @Function: ns9750_link_force + * @Return: void + * @Descr: configures eth and MII to use the link mode defined in + * ucLinkMode + ***********************************************************************/ + +static void ns9750_link_force (void) +{ + unsigned short uiControl; + + DEBUG_FN (DEBUG_LINK); + + uiControl = ns9750_mii_read (PHY_COMMON_CTRL); + uiControl &= ~(PHY_COMMON_CTRL_SPD_MA | + PHY_COMMON_CTRL_AUTO_NEG | PHY_COMMON_CTRL_DUPLEX); + + uiLastLinkStatus = 0; + + if ((ucLinkMode & FS_EEPROM_AUTONEG_SPEED_MASK) == + FS_EEPROM_AUTONEG_SPEED_100) { + uiControl |= PHY_COMMON_CTRL_SPD_100; + uiLastLinkStatus |= PHY_LXT971_STAT2_100BTX; + } else + uiControl |= PHY_COMMON_CTRL_SPD_10; + + if ((ucLinkMode & FS_EEPROM_AUTONEG_DUPLEX_MASK) == + FS_EEPROM_AUTONEG_DUPLEX_FULL) { + uiControl |= PHY_COMMON_CTRL_DUPLEX; + uiLastLinkStatus |= PHY_LXT971_STAT2_DUPLEX_MODE; + } + + ns9750_mii_write (PHY_COMMON_CTRL, uiControl); + + ns9750_link_print_changed (); + ns9750_link_update_egcr (); +} + +/*********************************************************************** + * @Function: ns9750_link_auto_negotiate + * @Return: void + * @Descr: performs auto-negotation of link. + ***********************************************************************/ + +static void ns9750_link_auto_negotiate (void) +{ + unsigned long ulStartJiffies; + unsigned short uiStatus; + + DEBUG_FN (DEBUG_LINK); + + /* run auto-negotation */ + /* define what we are capable of */ + ns9750_mii_write (PHY_COMMON_AUTO_ADV, + PHY_COMMON_AUTO_ADV_100BTXFD | + PHY_COMMON_AUTO_ADV_100BTX | + PHY_COMMON_AUTO_ADV_10BTFD | + PHY_COMMON_AUTO_ADV_10BT | + PHY_COMMON_AUTO_ADV_802_3); + /* start auto-negotiation */ + ns9750_mii_write (PHY_COMMON_CTRL, + PHY_COMMON_CTRL_AUTO_NEG | + PHY_COMMON_CTRL_RES_AUTO); + + /* wait for completion */ + + ulStartJiffies = get_ticks (); + while (get_ticks () < ulStartJiffies + NS9750_MII_NEG_DELAY) { + uiStatus = ns9750_mii_read (PHY_COMMON_STAT); + if ((uiStatus & + (PHY_COMMON_STAT_AN_COMP | PHY_COMMON_STAT_LNK_STAT)) == + (PHY_COMMON_STAT_AN_COMP | PHY_COMMON_STAT_LNK_STAT)) { + /* lucky we are, auto-negotiation succeeded */ + ns9750_link_print_changed (); + ns9750_link_update_egcr (); + return; + } + } + + DEBUG_ARGS0 (DEBUG_LINK, "auto-negotiation timed out\n"); + /* ignore invalid link settings */ +} + +/*********************************************************************** + * @Function: ns9750_link_update_egcr + * @Return: void + * @Descr: updates the EGCR and MAC2 link status after mode change or + * auto-negotation + ***********************************************************************/ + +static void ns9750_link_update_egcr (void) +{ + unsigned int unEGCR; + unsigned int unMAC2; + unsigned int unIPGT; + + DEBUG_FN (DEBUG_LINK); + + unEGCR = *get_eth_reg_addr (NS9750_ETH_EGCR1); + unMAC2 = *get_eth_reg_addr (NS9750_ETH_MAC2); + unIPGT = *get_eth_reg_addr (NS9750_ETH_IPGT) & ~NS9750_ETH_IPGT_MA; + + unMAC2 &= ~NS9750_ETH_MAC2_FULLD; + if ((uiLastLinkStatus & PHY_LXT971_STAT2_DUPLEX_MODE) + == PHY_LXT971_STAT2_DUPLEX_MODE) { + unMAC2 |= NS9750_ETH_MAC2_FULLD; + unIPGT |= 0x15; /* see [1] p. 339 */ + } else + unIPGT |= 0x12; /* see [1] p. 339 */ + + *get_eth_reg_addr (NS9750_ETH_MAC2) = unMAC2; + *get_eth_reg_addr (NS9750_ETH_EGCR1) = unEGCR; + *get_eth_reg_addr (NS9750_ETH_IPGT) = unIPGT; +} + +/*********************************************************************** + * @Function: ns9750_link_print_changed + * @Return: void + * @Descr: checks whether the link status has changed and if so prints + * the new mode + ***********************************************************************/ + +static void ns9750_link_print_changed (void) +{ + unsigned short uiStatus; + unsigned short uiControl; + + DEBUG_FN (DEBUG_LINK); + + uiControl = ns9750_mii_read (PHY_COMMON_CTRL); + + if ((uiControl & PHY_COMMON_CTRL_AUTO_NEG) == + PHY_COMMON_CTRL_AUTO_NEG) { + /* PHY_COMMON_STAT_LNK_STAT is only set on autonegotiation */ + uiStatus = ns9750_mii_read (PHY_COMMON_STAT); + + if (!(uiStatus & PHY_COMMON_STAT_LNK_STAT)) { + printk (KERN_WARNING NS9750_DRIVER_NAME + ": link down\n"); + /* @TODO Linux: carrier_off */ + } else { + /* @TODO Linux: carrier_on */ + if (phyDetected == PHY_LXT971A) { + uiStatus = ns9750_mii_read (PHY_LXT971_STAT2); + uiStatus &= (PHY_LXT971_STAT2_100BTX | + PHY_LXT971_STAT2_DUPLEX_MODE | + PHY_LXT971_STAT2_AUTO_NEG); + + /* mask out all uninteresting parts */ + } + /* other PHYs must store there link information in + uiStatus as PHY_LXT971 */ + } + } else { + /* mode has been forced, so uiStatus should be the same as the + last link status, enforce printing */ + uiStatus = uiLastLinkStatus; + uiLastLinkStatus = 0xff; + } + + if (uiStatus != uiLastLinkStatus) { + /* save current link status */ + uiLastLinkStatus = uiStatus; + + /* print new link status */ + + printk (KERN_INFO NS9750_DRIVER_NAME + ": link mode %i Mbps %s duplex %s\n", + (uiStatus & PHY_LXT971_STAT2_100BTX) ? 100 : 10, + (uiStatus & PHY_LXT971_STAT2_DUPLEX_MODE) ? "full" : + "half", + (uiStatus & PHY_LXT971_STAT2_AUTO_NEG) ? "(auto)" : + ""); + } +} + +/*********************************************************************** + * the MII low level stuff + ***********************************************************************/ + +/*********************************************************************** + * @Function: ns9750_mii_identify_phy + * @Return: 1 if supported PHY has been detected otherwise 0 + * @Descr: checks for supported PHY and prints the IDs. + ***********************************************************************/ + +static char ns9750_mii_identify_phy (void) +{ + unsigned short uiID1; + unsigned short uiID2; + unsigned char *szName; + char cRes = 0; + + DEBUG_FN (DEBUG_MII); + + phyDetected = (PhyType) uiID1 = ns9750_mii_read (PHY_COMMON_ID1); + + switch (phyDetected) { + case PHY_LXT971A: + szName = "LXT971A"; + uiID2 = ns9750_mii_read (PHY_COMMON_ID2); + nPhyMaxMdioClock = PHY_LXT971_MDIO_MAX_CLK; + cRes = 1; + break; + case PHY_NONE: + default: + /* in case uiID1 == 0 && uiID2 == 0 we may have the wrong + address or reset sets the wrong NS9750_ETH_MCFG_CLKS */ + + uiID2 = 0; + szName = "unknown"; + nPhyMaxMdioClock = PHY_MDIO_MAX_CLK; + phyDetected = PHY_NONE; + } + + printk (KERN_INFO NS9750_DRIVER_NAME + ": PHY (0x%x, 0x%x) = %s detected\n", uiID1, uiID2, szName); + + return cRes; +} + +/*********************************************************************** + * @Function: ns9750_mii_read + * @Return: the data read from PHY register uiRegister + * @Descr: the data read may be invalid if timed out. If so, a message + * is printed but the invalid data is returned. + * The fixed device address is being used. + ***********************************************************************/ + +static unsigned short ns9750_mii_read (unsigned short uiRegister) +{ + DEBUG_FN (DEBUG_MII_LOW); + + /* write MII register to be read */ + *get_eth_reg_addr (NS9750_ETH_MADR) = + NS9750_ETH_PHY_ADDRESS << 8 | uiRegister; + + *get_eth_reg_addr (NS9750_ETH_MCMD) = NS9750_ETH_MCMD_READ; + + if (!ns9750_mii_poll_busy ()) + printk (KERN_WARNING NS9750_DRIVER_NAME + ": MII still busy in read\n"); + /* continue to read */ + + *get_eth_reg_addr (NS9750_ETH_MCMD) = 0; + + return (unsigned short) (*get_eth_reg_addr (NS9750_ETH_MRDD)); +} + + +/*********************************************************************** + * @Function: ns9750_mii_write + * @Return: nothing + * @Descr: writes the data to the PHY register. In case of a timeout, + * no special handling is performed but a message printed + * The fixed device address is being used. + ***********************************************************************/ + +static void ns9750_mii_write (unsigned short uiRegister, + unsigned short uiData) +{ + DEBUG_FN (DEBUG_MII_LOW); + + /* write MII register to be written */ + *get_eth_reg_addr (NS9750_ETH_MADR) = + NS9750_ETH_PHY_ADDRESS << 8 | uiRegister; + + *get_eth_reg_addr (NS9750_ETH_MWTD) = uiData; + + if (!ns9750_mii_poll_busy ()) { + printf (KERN_WARNING NS9750_DRIVER_NAME + ": MII still busy in write\n"); + } +} + + +/*********************************************************************** + * @Function: ns9750_mii_get_clock_divisor + * @Return: the clock divisor that should be used in NS9750_ETH_MCFG_CLKS + * @Descr: if no clock divisor can be calculated for the + * current SYSCLK and the maximum MDIO Clock, a warning is printed + * and the greatest divisor is taken + ***********************************************************************/ + +static unsigned int ns9750_mii_get_clock_divisor (unsigned int unMaxMDIOClk) +{ + struct { + unsigned int unSysClkDivisor; + unsigned int unClks; /* field for NS9750_ETH_MCFG_CLKS */ + } PHYClockDivisors[] = { + { + 4, NS9750_ETH_MCFG_CLKS_4}, { + 6, NS9750_ETH_MCFG_CLKS_6}, { + 8, NS9750_ETH_MCFG_CLKS_8}, { + 10, NS9750_ETH_MCFG_CLKS_10}, { + 20, NS9750_ETH_MCFG_CLKS_20}, { + 30, NS9750_ETH_MCFG_CLKS_30}, { + 40, NS9750_ETH_MCFG_CLKS_40} + }; + + int nIndexSysClkDiv; + int nArraySize = + sizeof (PHYClockDivisors) / sizeof (PHYClockDivisors[0]); + unsigned int unClks = NS9750_ETH_MCFG_CLKS_40; /* defaults to + greatest div */ + + DEBUG_FN (DEBUG_INIT); + + for (nIndexSysClkDiv = 0; nIndexSysClkDiv < nArraySize; + nIndexSysClkDiv++) { + /* find first sysclock divisor that isn't higher than 2.5 MHz + clock */ + if (AHB_CLK_FREQ / + PHYClockDivisors[nIndexSysClkDiv].unSysClkDivisor <= + unMaxMDIOClk) { + unClks = PHYClockDivisors[nIndexSysClkDiv].unClks; + break; + } + } + + DEBUG_ARGS2 (DEBUG_INIT, + "Taking MDIO Clock bit mask 0x%0x for max clock %i\n", + unClks, unMaxMDIOClk); + + /* return greatest divisor */ + return unClks; +} + +/*********************************************************************** + * @Function: ns9750_mii_poll_busy + * @Return: 0 if timed out otherwise the remaing timeout + * @Descr: waits until the MII has completed a command or it times out + * code may be interrupted by hard interrupts. + * It is not checked what happens on multiple actions when + * the first is still being busy and we timeout. + ***********************************************************************/ + +static unsigned int ns9750_mii_poll_busy (void) +{ + unsigned int unTimeout = 10000; + + DEBUG_FN (DEBUG_MII_LOW); + + while (((*get_eth_reg_addr (NS9750_ETH_MIND) & NS9750_ETH_MIND_BUSY) + == NS9750_ETH_MIND_BUSY) && unTimeout) + unTimeout--; + + return unTimeout; +} + +#endif /* CONFIG_DRIVER_NS9750_ETHERNET */ diff --git a/drivers/ns9750_serial.c b/drivers/ns9750_serial.c new file mode 100644 index 000000000..aced3dae8 --- /dev/null +++ b/drivers/ns9750_serial.c @@ -0,0 +1,212 @@ +/*********************************************************************** + * + * Copyright (C) 2004 by FS Forth-Systeme GmbH. + * All rights reserved. + * + * $Id: ns9750_serial.c,v 1.1 2004/02/16 10:37:20 mpietrek Exp $ + * @Author: Markus Pietrek + * @Descr: Serial driver for the NS9750. Only one UART is supported yet. + * @References: [1] NS9750 Hardware Reference/December 2003 + * @TODO: Implement Character GAP Timer when chip is fixed for PLL bypass + * + * 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 + +#ifdef CFG_NS9750_UART + +#include "ns9750_bbus.h" /* for GPIOs */ +#include "ns9750_ser.h" /* for serial configuration */ + +#define CONSOLE CONFIG_CONS_INDEX + +static unsigned int calcBitrateRegister( void ); +static unsigned int calcRxCharGapRegister( void ); + +static char cCharsAvailable; /* Numbers of chars in unCharCache */ +static unsigned int unCharCache; /* unCharCache is only valid if + * cCharsAvailable > 0 */ + +/*********************************************************************** + * @Function: serial_init + * @Return: 0 + * @Descr: configures GPIOs and UART. Requires BBUS Master Reset turned off + ***********************************************************************/ + +int serial_init( void ) +{ + unsigned int aunGPIOTxD[] = { 0, 8, 40, 44 }; + unsigned int aunGPIORxD[] = { 1, 9, 41, 45 }; + + cCharsAvailable = 0; + + /* configure TxD and RxD pins for their special function */ + set_gpio_cfg_reg_val( aunGPIOTxD[ CONSOLE ], + NS9750_GPIO_CFG_FUNC_0 | NS9750_GPIO_CFG_OUTPUT ); + set_gpio_cfg_reg_val( aunGPIORxD[ CONSOLE ], + NS9750_GPIO_CFG_FUNC_0 | NS9750_GPIO_CFG_INPUT ); + + /* configure serial engine */ + *get_ser_reg_addr_channel( NS9750_SER_CTRL_A, CONSOLE ) = + NS9750_SER_CTRL_A_CE | + NS9750_SER_CTRL_A_STOP | + NS9750_SER_CTRL_A_WLS_8; + + serial_setbrg(); + + *get_ser_reg_addr_channel( NS9750_SER_CTRL_B, CONSOLE ) = + NS9750_SER_CTRL_B_RCGT; + + return 0; +} + +/*********************************************************************** + * @Function: serial_putc + * @Return: n/a + * @Descr: writes one character to the FIFO. Blocks until FIFO is not full + ***********************************************************************/ + +void serial_putc( const char c ) +{ + if (c == '\n') + serial_putc( '\r' ); + + while (!(*get_ser_reg_addr_channel( NS9750_SER_STAT_A, CONSOLE) & + NS9750_SER_STAT_A_TRDY ) ) { + /* do nothing, wait for characters in FIFO sent */ + } + + *(volatile char*) get_ser_reg_addr_channel( NS9750_SER_FIFO, + CONSOLE) = c; +} + +/*********************************************************************** + * @Function: serial_puts + * @Return: n/a + * @Descr: writes non-zero string to the FIFO. + ***********************************************************************/ + +void serial_puts( const char *s ) +{ + while (*s) { + serial_putc( *s++ ); + } +} + +/*********************************************************************** + * @Function: serial_getc + * @Return: the character read + * @Descr: performs only 8bit accesses to the FIFO. No error handling + ***********************************************************************/ + +int serial_getc( void ) +{ + int i; + + while (!serial_tstc() ) { + /* do nothing, wait for incoming characters */ + } + + /* at least one character in unCharCache */ + i = (int) (unCharCache & 0xff); + + unCharCache >>= 8; + cCharsAvailable--; + + return i; +} + +/*********************************************************************** + * @Function: serial_tstc + * @Return: 0 if no input available, otherwise != 0 + * @Descr: checks for incoming FIFO not empty. Stores the incoming chars in + * unCharCache and the numbers of characters in cCharsAvailable + ***********************************************************************/ + +int serial_tstc( void ) +{ + unsigned int unRegCache; + + if ( cCharsAvailable ) + return 1; + + unRegCache = *get_ser_reg_addr_channel( NS9750_SER_STAT_A,CONSOLE ); + if( unRegCache & NS9750_SER_STAT_A_RBC ) { + *get_ser_reg_addr_channel( NS9750_SER_STAT_A, CONSOLE ) = + NS9750_SER_STAT_A_RBC; + unRegCache = *get_ser_reg_addr_channel( NS9750_SER_STAT_A, + CONSOLE ); + } + + if ( unRegCache & NS9750_SER_STAT_A_RRDY ) { + cCharsAvailable = (unRegCache & NS9750_SER_STAT_A_RXFDB_MA)>>20; + if ( !cCharsAvailable ) + cCharsAvailable = 4; + + unCharCache = *get_ser_reg_addr_channel( NS9750_SER_FIFO, + CONSOLE ); + return 1; + } + + /* no chars available */ + return 0; +} + +void serial_setbrg( void ) +{ + *get_ser_reg_addr_channel( NS9750_SER_BITRATE, CONSOLE ) = + calcBitrateRegister(); + *get_ser_reg_addr_channel( NS9750_SER_RX_CHAR_TIMER, CONSOLE ) = + calcRxCharGapRegister(); +} + +/*********************************************************************** + * @Function: calcBitrateRegister + * @Return: value for the serial bitrate register + * @Descr: register value depends on clock frequency and baudrate + ***********************************************************************/ + +static unsigned int calcBitrateRegister( void ) +{ + DECLARE_GLOBAL_DATA_PTR; + + return ( NS9750_SER_BITRATE_EBIT | + NS9750_SER_BITRATE_CLKMUX_BCLK | + NS9750_SER_BITRATE_TMODE | + NS9750_SER_BITRATE_TCDR_16 | + NS9750_SER_BITRATE_RCDR_16 | + ( ( ( ( CONFIG_SYS_CLK_FREQ / 8 ) / /* BBUS clock,[1] Fig. 38 */ + ( gd->baudrate * 16 ) ) - 1 ) & + NS9750_SER_BITRATE_N_MA ) ); +} + +/*********************************************************************** + * @Function: calcRxCharGapRegister + * @Return: value for the character gap timer register + * @Descr: register value depends on clock frequency and baudrate. Currently 0 + * is used as there is a bug with the gap timer in PLL bypass mode. + ***********************************************************************/ + +static unsigned int calcRxCharGapRegister( void ) +{ + DECLARE_GLOBAL_DATA_PTR; + + return NS9750_SER_RX_CHAR_TIMER_TRUN; +} + +#endif /* CFG_NS9750_UART */ diff --git a/fs/fat/fat.c b/fs/fat/fat.c index daa70349d..6f1e57cbc 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -89,7 +89,8 @@ fat_register_device(block_dev_desc_t *dev_desc, int part_no) part_offset=0; } else { -#if (CONFIG_COMMANDS & CFG_CMD_IDE) || (CONFIG_COMMANDS & CFG_CMD_SCSI) +#if (CONFIG_COMMANDS & CFG_CMD_IDE) || (CONFIG_COMMANDS & CFG_CMD_SCSI) || \ + (CONFIG_COMMANDS & CFG_CMD_USB) disk_partition_t info; if(!get_partition_info(dev_desc, part_no, &info)) { part_offset = info.start; diff --git a/include/configs/IceCube.h b/include/configs/IceCube.h index 888b16523..1dc992598 100644 --- a/include/configs/IceCube.h +++ b/include/configs/IceCube.h @@ -1,5 +1,5 @@ /* - * (C) Copyright 2003 + * (C) Copyright 2003-2004 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * See file CREDITS for list of people who contributed to this @@ -81,11 +81,22 @@ #endif +/* USB */ +#if 1 +#define CONFIG_USB_OHCI +#define ADD_USB_CMD CFG_CMD_USB | CFG_CMD_FAT +#define CONFIG_DOS_PARTITION +#define CONFIG_USB_STORAGE +#else +#define ADD_USB_CMD 0 +#endif + /* * Supported commands */ #define CONFIG_COMMANDS (CONFIG_CMD_DFL | ADD_PCI_CMD | \ - CFG_CMD_I2C | CFG_CMD_EEPROM) + CFG_CMD_I2C | CFG_CMD_EEPROM | \ + ADD_USB_CMD) /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ #include diff --git a/include/configs/eXalion.h b/include/configs/eXalion.h new file mode 100644 index 000000000..5ebc7a9cc --- /dev/null +++ b/include/configs/eXalion.h @@ -0,0 +1,454 @@ +/* + * (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 + */ + +/* ------------------------------------------------------------------------- */ + +/* + * 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_MPC8245 1 +#define CONFIG_EXALION 1 + +#if defined (CONFIG_MPC8240) + /* #warning ---------- eXalion with MPC8240 --------------- */ +#elif defined (CONFIG_MPC8245) + /* #warning ++++++++++ eXalion with MPC8245 +++++++++++++++ */ +#elif defined (CONFIG_MPC8245) && defined (CONFIG_MPC8245) +#error #### Both types of MPC824x defined (CONFIG_8240 and CONFIG_8245) +#else +#error #### Specific type of MPC824x must be defined (i.e. CONFIG_MPC8240) +#endif +/* older kernels need clock in MHz newer in Hz */ + /* #define CONFIG_CLOCKS_IN_MHZ 1 *//* clocks passsed to Linux in MHz */ +#undef CONFIG_CLOCKS_IN_MHZ + +#define CONFIG_BOOTDELAY 10 + + + /*#define CONFIG_DRAM_SPEED 66 *//* MHz */ + +#define CONFIG_COMMANDS ( CONFIG_CMD_DFL | \ + CFG_CMD_FLASH | \ + CFG_CMD_SDRAM | \ + CFG_CMD_I2C | \ + CFG_CMD_IDE | \ + CFG_CMD_FAT | \ + CFG_CMD_ENV | \ + CFG_CMD_PCI ) + +/* 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 8 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ +#define CFG_LOAD_ADDR 0x00100000 /* default load address */ + +#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } + +#define CONFIG_MISC_INIT_R 1 + +/*----------------------------------------------------------------------- + * 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 /* 1 GBytes - initdram() will */ + /* return real value. */ + +#define CFG_RESET_ADDRESS 0xFFF00100 + +#undef CFG_RAMBOOT +#define CFG_MONITOR_LEN (256 << 10) /* Reserve 256 kB for Monitor */ +#define CFG_MONITOR_BASE TEXT_BASE + +/*----------------------------------------------------------------------- + * Definitions for initial stack pointer and data area + */ +#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_GBL_DATA_SIZE 256 /* size in bytes reserved for initial data */ +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) +#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET + + +#if defined (CONFIG_MPC8240) +#define CFG_FLASH_BASE 0xFFE00000 +#define CFG_FLASH_SIZE (2 * 1024 * 1024) /* onboard 2MByte flash */ +#elif defined (CONFIG_MPC8245) +#define CFG_FLASH_BASE 0xFFC00000 +#define CFG_FLASH_SIZE (4 * 1024 * 1024) /* onboard 4MByte flash */ +#else +#error Specific type of MPC824x must be defined (i.e. CONFIG_MPC8240) +#endif + +#define CFG_ENV_IS_IN_FLASH 1 +#define CFG_ENV_SECT_SIZE 0x20000 /* Size of one Flash sector */ +#define CFG_ENV_SIZE CFG_ENV_SECT_SIZE /* Use one Flash sector for enviroment */ +#define CFG_ENV_ADDR 0xFFFC0000 +#define CFG_ENV_OFFSET 0 /* starting right at the beginning */ + +#define CFG_MALLOC_LEN (128 * 1024) /* Reserve 128 kB for malloc() */ + +#define CFG_ALT_MEMTEST 1 /* use real memory test */ +#define CFG_MEMTEST_START 0x00004000 /* memtest works on */ +#define CFG_MEMTEST_END 0x02000000 /* 0 ... 32 MB in DRAM */ + +#define CFG_EUMB_ADDR 0xFC000000 + +/* #define CFG_ISA_MEM 0xFD000000 */ +#define CFG_ISA_IO 0xFE000000 + +/*----------------------------------------------------------------------- + * FLASH organization + */ +#define CFG_MAX_FLASH_BANKS 1 /* Max number of flash banks */ +#define CFG_MAX_FLASH_SECT 64 /* Max number of sectors per flash */ + +#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ + +#define FLASH_BASE0_PRELIM CFG_FLASH_BASE +#define FLASH_BASE1_PRELIM 0 + + +/*----------------------------------------------------------------------- + * FLASH and environment organization + */ + +#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */ +#define CFG_FLASH_CFI_DRIVER 1 /* Use the common driver */ +#define CFG_MAX_FLASH_SECT 64 /* max number of sectors on one chip */ +#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */ +#define CFG_FLASH_INCREMENT 0 /* there is only one bank */ +#define CFG_FLASH_PROTECTION 1 /* use hardware protection */ +#define CFG_FLASH_USE_BUFFER_WRITE 1 /* use buffered writes (20x faster) */ + + +/*----------------------------------------------------------------------- + * PCI stuff + */ +#define CONFIG_PCI 1 /* include pci support */ +#undef CONFIG_PCI_PNP + +#define CONFIG_NET_MULTI 1 /* Multi ethernet cards support */ + +#define CONFIG_EEPRO100 1 + +#define PCI_ENET0_MEMADDR 0x80000000 /* Intel 82559ER */ +#define PCI_ENET0_IOADDR 0x80000000 +#define PCI_ENET1_MEMADDR 0x81000000 /* Intel 82559ER */ +#define PCI_ENET1_IOADDR 0x81000000 +#define PCI_ENET2_MEMADDR 0x82000000 /* Broadcom BCM569xx */ +#define PCI_ENET2_IOADDR 0x82000000 +#define PCI_ENET3_MEMADDR 0x83000000 /* Broadcom BCM56xx */ +#define PCI_ENET3_IOADDR 0x83000000 + +/*----------------------------------------------------------------------- + * NS16550 Configuration + */ +#define CFG_NS16550 1 +#define CFG_NS16550_SERIAL 1 + +#define CONFIG_CONS_INDEX 1 +#define CONFIG_BAUDRATE 38400 + +#define CFG_NS16550_REG_SIZE 1 + +#if (CONFIG_CONS_INDEX == 1) +#define CFG_NS16550_CLK 1843200 /* COM1 only ! */ +#else +#define CFG_NS16550_CLK ({ extern ulong get_bus_freq (ulong); get_bus_freq (0); }) +#endif + +#define CFG_NS16550_COM1 (CFG_ISA_IO + 0x3F8) +#define CFG_NS16550_COM2 (CFG_EUMB_ADDR + 0x4500) +#define CFG_NS16550_COM3 (CFG_EUMB_ADDR + 0x4600) + +/*----------------------------------------------------------------------- + * select i2c support configuration + * + * Supported configurations are {none, software, hardware} drivers. + * If the software driver is chosen, there are some additional + * configuration items that the driver uses to drive the port pins. + */ +#define CONFIG_HARD_I2C 1 /* To enable I2C support */ +#undef CONFIG_SOFT_I2C /* I2C bit-banged */ +#define CFG_I2C_SPEED 400000 /* I2C speed and slave address */ +#define CFG_I2C_SLAVE 0x7F + +/*----------------------------------------------------------------------- + * Low Level Configuration Settings + * (address mappings, register initial values, etc.) + * You should know what you are doing if you make changes here. + */ +#define CFG_HZ 1000 + +#define CONFIG_SYS_CLK_FREQ 33333333 /* external frequency to pll */ +#define CONFIG_PLL_PCI_TO_MEM_MULTIPLIER 2 /* for MPC8240 only */ + + /*#define CONFIG_133MHZ_DRAM 1 *//* For 133 MHZ DRAM only !!!!!!!!!!! */ + +#if defined (CONFIG_MPC8245) +/* Bit-field values for PMCR2. */ +#if defined (CONFIG_133MHZ_DRAM) +#define CFG_DLL_EXTEND 0x80 /* use DLL extended range - 133MHz only */ +#define CFG_PCI_HOLD_DEL 0x20 /* delay and hold timing - 133MHz only */ +#endif + +/* Bit-field values for MIOCR1. */ +#if !defined (CONFIG_133MHZ_DRAM) +#define CFG_DLL_MAX_DELAY 0x04 /* longer DLL delay line - 66MHz only */ +#endif +/* Bit-field values for MIOCR2. */ +#define CFG_SDRAM_DSCD 0x20 /* SDRAM data in sample clock delay */ + /* - note bottom 3 bits MUST be 0 */ +#endif + +/* Bit-field values for MCCR1. */ +#define CFG_ROMNAL 7 /*rom/flash next access time */ +#define CFG_ROMFAL 11 /*rom/flash access time */ + +/* Bit-field values for MCCR2. */ +#define CFG_TSWAIT 0x5 /* Transaction Start Wait States timer */ +#if defined (CONFIG_133MHZ_DRAM) +#define CFG_REFINT 1300 /* no of clock cycles between CBR */ +#else /* refresh cycles */ +#define CFG_REFINT 750 +#endif + +/* Burst To Precharge. Bits of this value go to MCCR3 and MCCR4. */ +#if defined (CONFIG_133MHZ_DRAM) +#define CFG_BSTOPRE 1023 +#else +#define CFG_BSTOPRE 250 +#endif + +/* Bit-field values for MCCR3. */ +/* the following are for SDRAM only */ + +#if defined (CONFIG_133MHZ_DRAM) +#define CFG_REFREC 9 /* Refresh to activate interval */ +#else +#define CFG_REFREC 5 /* Refresh to activate interval */ +#endif +#if defined (CONFIG_MPC8240) +#define CFG_RDLAT 2 /* data latency from read command */ +#endif + +/* Bit-field values for MCCR4. */ +#if defined (CONFIG_133MHZ_DRAM) +#define CFG_PRETOACT 3 /* Precharge to activate interval */ +#define CFG_ACTTOPRE 7 /* Activate to Precharge interval */ +#define CFG_ACTORW 5 /* Activate to R/W */ +#define CFG_SDMODE_CAS_LAT 3 /* SDMODE CAS latency */ +#else +#if 0 +#define CFG_PRETOACT 2 /* Precharge to activate interval */ +#define CFG_ACTTOPRE 3 /* Activate to Precharge interval */ +#define CFG_ACTORW 3 /* Activate to R/W */ +#define CFG_SDMODE_CAS_LAT 2 /* SDMODE CAS latency */ +#endif +#define CFG_PRETOACT 2 /* Precharge to activate interval */ +#define CFG_ACTTOPRE 5 /* Activate to Precharge interval */ +#define CFG_ACTORW 3 /* Activate to R/W */ +#define CFG_SDMODE_CAS_LAT 3 /* SDMODE CAS latency */ +#endif +#define CFG_SDMODE_WRAP 0 /* SDMODE wrap type */ +#define CFG_SDMODE_BURSTLEN 2 /* SDMODE Burst length 2=4, 3=8 */ +#define CFG_REGDIMM 0 +#if defined (CONFIG_MPC8240) +#define CFG_REGISTERD_TYPE_BUFFER 0 +#elif defined (CONFIG_MPC8245) +#define CFG_REGISTERD_TYPE_BUFFER 1 +#define CFG_EXTROM 0 +#else +#error Specific type of MPC824x must be defined (i.e. CONFIG_MPC8240) +#endif + + +/*----------------------------------------------------------------------- + memory bank settings + * only bits 20-29 are actually used from these vales to set the + * start/end 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 0x3ff00000 +#define CFG_BANK1_END 0x3fffffff +#define CFG_BANK1_ENABLE 0 +#define CFG_BANK2_START 0x3ff00000 +#define CFG_BANK2_END 0x3fffffff +#define CFG_BANK2_ENABLE 0 +#define CFG_BANK3_START 0x3ff00000 +#define CFG_BANK3_END 0x3fffffff +#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 + +#if defined (CONFIG_MPC8240) +#define CFG_ODCR 0xDF /* configures line driver impedances, */ + /* see 8240 book for bit definitions */ +#elif defined (CONFIG_MPC8245) +#if defined (CONFIG_133MHZ_DRAM) +#define CFG_ODCR 0xFE /* configures line driver impedances - 133MHz */ +#else +#define CFG_ODCR 0xDE /* configures line driver impedances - 66MHz */ +#endif +#else +#error Specific type of MPC824x must be defined (i.e. CONFIG_MPC8240) +#endif + +#define CFG_PGMAX 0x32 /* how long the 8240 retains the */ + /* currently accessed page in memory */ + /* see 8240 book for details */ + +/*----------------------------------------------------------------------- + * Block Address Translation (BAT) register settings. + */ +/* 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) + +/* stack in DCACHE @ 1GB (no backing mem) */ +#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 */ +#define CFG_IBAT2L (0x80000000 | BATL_PP_10 | BATL_CACHEINHIBIT) +#define CFG_IBAT2U (0x80000000 | BATU_BL_256M | BATU_VS | BATU_VP) + +/* Flash, 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 + + +/*----------------------------------------------------------------------- + * Cache Configuration + */ +#define CFG_CACHELINE_SIZE 32 +#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 */ + + +/* values according to the manual */ +#define CONFIG_DRAM_50MHZ 1 +#define CONFIG_SDRAM_50MHZ + +#undef NR_8259_INTS +#define NR_8259_INTS 1 + +/*----------------------------------------------------------------------- + * IDE/ATA stuff + */ +#define CFG_IDE_MAXBUS 1 /* max. 2 IDE busses */ +#define CFG_IDE_MAXDEVICE (CFG_IDE_MAXBUS*1) /* max. 2 drives per IDE bus */ + +#define CFG_ATA_BASE_ADDR CFG_ISA_IO /* base address */ +#define CFG_ATA_IDE0_OFFSET 0x01F0 /* ide0 offste */ +#define CFG_ATA_IDE1_OFFSET 0x0170 /* ide1 offset */ +#define CFG_ATA_DATA_OFFSET 0 /* data reg offset */ +#define CFG_ATA_REG_OFFSET 0 /* reg offset */ +#define CFG_ATA_ALT_OFFSET 0x200 /* alternate register offset */ + +#define CONFIG_ATAPI + +#undef CONFIG_IDE_8xx_DIRECT /* no pcmcia interface required */ +#undef CONFIG_IDE_LED /* no led for ide supported */ +#undef CONFIG_IDE_RESET /* reset for ide supported... */ +#undef CONFIG_IDE_RESET_ROUTINE /* with a special reset function */ + +/*----------------------------------------------------------------------- + * DISK Partition support + */ +#define CONFIG_DOS_PARTITION + +/*----------------------------------------------------------------------- + * 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 */ + +#endif /* __CONFIG_H */ diff --git a/include/configs/ns9750dev.h b/include/configs/ns9750dev.h new file mode 100644 index 000000000..11d21b20d --- /dev/null +++ b/include/configs/ns9750dev.h @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2004 by FS Forth-Systeme GmbH. + * All rights reserved. + * Markus Pietrek + * + * Configuation settings for the NetSilicon NS9750 DevBoard + * + * 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 __CONFIG_H +#define __CONFIG_H + +/* + * If we are developing, we might want to start armboot from ram + * so we MUST NOT initialize critical regs like mem-timing ... + */ +#define CONFIG_INIT_CRITICAL /* undef for developing */ + +/* + * High Level Configuration Options + * (easy to change) + */ +#define CONFIG_ARM926EJS 1 /* This is an ARM926EJS Core */ +#define CONFIG_NS9750 1 /* in an NetSilicon NS9750 SoC */ +#define CONFIG_NS9750DEV 1 /* on an NetSilicon NS9750 DevBoard */ + +/* input clock of PLL */ +#define CONFIG_SYS_CLK_FREQ 324403200 /* Don't use PLL. SW11-4 off */ + +#define CPU_CLK_FREQ (CONFIG_SYS_CLK_FREQ/2) +#define AHB_CLK_FREQ (CONFIG_SYS_CLK_FREQ/4) +#define BBUS_CLK_FREQ (CONFIG_SYS_CLK_FREQ/8) + +#undef CONFIG_USE_IRQ /* we don't need IRQ/FIQ stuff */ +/*@TODO #define CONFIG_STATUS_LED*/ +#define CONFIG_USE_IRQ + +/* + * Size of malloc() pool + */ +#define CFG_MALLOC_LEN (CFG_ENV_SIZE + 128*1024) +#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for initial + * data */ + +/* + * Hardware drivers + */ +#define CFG_NS9750_UART 1 /* use on-chip UART */ +#define CONFIG_DRIVER_NS9750_ETHERNET 1 /* use on-chip ethernet */ + +/* + * select serial console configuration + */ +#define CONFIG_CONS_INDEX 1 /* Port B */ + +/* allow to overwrite serial and ethaddr */ +#define CONFIG_ENV_OVERWRITE + +#define CONFIG_BAUDRATE 38400 + +/*********************************************************** + * Command definition + ***********************************************************/ +#if 0 /* @TODO */ +#define CONFIG_COMMANDS \ + (CONFIG_CMD_DFL | \ + CFG_CMD_CACHE | \ + /*CFG_CMD_NAND |*/ \ + /*CFG_CMD_EEPROM |*/ \ + /*CFG_CMD_I2C |*/ \ + /*CFG_CMD_USB |*/ \ + CFG_CMD_REGINFO | \ + CFG_CMD_DATE | \ + CFG_CMD_ELF) +#else +#define CONFIG_COMMANDS \ + (CONFIG_CMD_BDI | \ + CFG_CMD_NET | \ + CFG_CMD_PING | \ + CFG_CMD_CONSOLE | \ + CFG_CMD_LOADB | \ + CFG_CMD_LOADS | \ + CFG_CMD_MEMORY) +#endif + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include + +#define CONFIG_BOOTDELAY 3 +/*#define CONFIG_BOOTARGS "root=ramfs devfs=mount console=ttySA0,9600" */ + +#define CONFIG_ETHADDR 00:04:f3:ff:ff:fb /*@TODO unset */ +#define CONFIG_NETMASK 255.255.255.0 +#define CONFIG_IPADDR 192.168.42.30 +#define CONFIG_SERVERIP 192.168.42.1 + +/*#define CONFIG_BOOTFILE "elinos-lart" */ +/*#define CONFIG_BOOTCOMMAND "tftp; bootm" */ + +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CONFIG_KGDB_BAUDRATE 115200 /* speed to run kgdb serial port */ +/* what's this ? it's not used anywhere */ +#define CONFIG_KGDB_SER_INDEX 1 /* which serial port to use */ +#endif + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "NS9750DEV # " /* 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_MEMTEST_START 0x00000000 /* memtest works on */ +#define CFG_MEMTEST_END 0x00780000 /* 7,5 MB in DRAM */ /* @TODO */ + +#undef CFG_CLKS_IN_HZ /* everything, incl board info, in Hz */ + +#define CFG_LOAD_ADDR 0x00600000 /* default load address */ /* @TODO */ + +#define CFG_HZ (CPU_CLK_FREQ/64) + +/* valid baudrates */ +#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } + +#define NS9750_ETH_PHY_ADDRESS (0x0000) + +/*----------------------------------------------------------------------- + * Stack sizes + * + * The stack sizes are set up in start.S using the settings below + */ +#define CONFIG_STACKSIZE (128*1024) /* regular stack */ +#ifdef CONFIG_USE_IRQ +#define CONFIG_STACKSIZE_IRQ (4*1024) /* IRQ stack */ +#define CONFIG_STACKSIZE_FIQ (4*1024) /* FIQ stack */ +#endif + +/*----------------------------------------------------------------------- + * Physical Memory Map + */ +/* TODO */ +#define CONFIG_NR_DRAM_BANKS 2 /* we have 1 bank of DRAM */ +#define PHYS_SDRAM_1 0x00000000 /* SDRAM Bank #1 */ +#define PHYS_SDRAM_1_SIZE 0x00800000 /* 8 MB */ +#define PHYS_SDRAM_2 0x10000000 /* SDRAM Bank #1 */ +#define PHYS_SDRAM_2_SIZE 0x00800000 /* 8 MB */ + +#define PHYS_FLASH_1 0x50000000 /* Flash Bank #1 */ + +#define CFG_FLASH_BASE PHYS_FLASH_1 + +/*----------------------------------------------------------------------- + * FLASH and environment organization + */ + +/* @TODO*/ +#define CONFIG_AMD_LV400 1 /* uncomment this if you have a LV400 flash */ +#if 0 +#define CONFIG_AMD_LV800 1 /* uncomment this if you have a LV800 flash */ +#endif + +#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */ +#ifdef CONFIG_AMD_LV800 +#define PHYS_FLASH_SIZE 0x00100000 /* 1MB */ +#define CFG_MAX_FLASH_SECT (19) /* max number of sectors on one chip */ +#define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x0F0000) /* addr of environment */ +#endif +#ifdef CONFIG_AMD_LV400 +#define PHYS_FLASH_SIZE 0x00080000 /* 512KB */ +#define CFG_MAX_FLASH_SECT (11) /* max number of sectors on one chip */ +#define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x070000) /* addr of environment */ +#endif + +/* timeout values are in ticks */ +#define CFG_FLASH_ERASE_TOUT (5*CFG_HZ) /* Timeout for Flash Erase */ +#define CFG_FLASH_WRITE_TOUT (5*CFG_HZ) /* Timeout for Flash Write */ + +/* @TODO */ +/*#define CFG_ENV_IS_IN_FLASH 1*/ +#define CFG_ENV_IS_NOWHERE +#define CFG_ENV_SIZE 0x10000 /* Total Size of Environment Sector */ + +#ifdef CONFIG_STATUS_LED + +extern void __led_init(led_id_t mask, int state); +extern void __led_toggle(led_id_t mask); +extern void __led_set(led_id_t mask, int state); + +#endif /* CONFIG_STATUS_LED */ + +#endif /* __CONFIG_H */ diff --git a/include/mpc5xxx.h b/include/mpc5xxx.h index 49951f597..8d4013a16 100644 --- a/include/mpc5xxx.h +++ b/include/mpc5xxx.h @@ -90,6 +90,7 @@ #define MPC5XXX_GPT (CFG_MBAR + 0x0600) #define MPC5XXX_GPIO (CFG_MBAR + 0x0b00) #define MPC5XXX_PCI (CFG_MBAR + 0x0d00) +#define MPC5XXX_USB (CFG_MBAR + 0x1000) #define MPC5XXX_SDMA (CFG_MBAR + 0x1200) #define MPC5XXX_XLBARB (CFG_MBAR + 0x1f00) @@ -132,6 +133,7 @@ #define MPC5XXX_CDM_JTAGID (MPC5XXX_CDM + 0x0000) #define MPC5XXX_CDM_PORCFG (MPC5XXX_CDM + 0x0004) #define MPC5XXX_CDM_CFG (MPC5XXX_CDM + 0x000c) +#define MPC5XXX_CDM_48_FDC (MPC5XXX_CDM + 0x0010) #define MPC5XXX_CDM_SRESET (MPC5XXX_CDM + 0x0020) /* Local Plus Bus interface */ diff --git a/include/ns9750_bbus.h b/include/ns9750_bbus.h new file mode 100644 index 000000000..0918931cb --- /dev/null +++ b/include/ns9750_bbus.h @@ -0,0 +1,125 @@ +/*********************************************************************** + * + * Copyright (C) 2004 by FS Forth-Systeme GmbH. + * All rights reserved. + * + * $Id: ns9750_bbus.h,v 1.1 2004/02/16 10:37:20 mpietrek Exp $ + * @Author: Markus Pietrek + * @Descr: Definitions for BBus usage + * @References: [1] NS9750 Hardware Reference Manual/December 2003 Chap. 10 + * + * 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 FS_NS9750_BBUS_H +#define FS_NS9750_BBUS_H + +#define NS9750_BBUS_MODULE_BASE (0x90600000) + +#define get_bbus_reg_addr(c) \ + ((volatile unsigned int *)(NS9750_BBUS_MODULE_BASE+(unsigned int) (c))) + +/* We have support for 50 GPIO pins */ + +#define get_gpio_cfg_reg_addr(pin) \ + get_bbus_reg_addr( NS9750_BBUS_GPIO_CFG_BASE + (((pin) >> 3) * 4) ) + +/* To Read/Modify/Write a pin configuration register, use it like + set_gpio_cfg_reg_val( 12, NS9750_GPIO_CFG_FUNC_GPIO|NS9750_GPIO_CFG_OUTPUT ); + They should be wrapped by cli()/sti() */ +#define set_gpio_cfg_reg_val(pin,cfg) \ + *get_gpio_cfg_reg_addr(pin)=(*get_gpio_cfg_reg_addr((pin)) & \ + ~NS9750_GPIO_CFG_MASK((pin))) |\ + NS9750_GPIO_CFG_VAL((pin),(cfg)); + +#define NS9750_GPIO_CFG_MASK(pin) (NS9750_GPIO_CFG_VAL(pin, \ + NS9750_GPIO_CFG_MA)) +#define NS9750_GPIO_CFG_VAL(pin,cfg) ((cfg) << (((pin) % 8) * 4)) + +#define NS9750_GPIO_CFG_MA (0x0F) +#define NS9750_GPIO_CFG_INPUT (0x00) +#define NS9750_GPIO_CFG_OUTPUT (0x08) +#define NS9750_GPIO_CFG_FUNC_GPIO (0x03) +#define NS9750_GPIO_CFG_FUNC_2 (0x02) +#define NS9750_GPIO_CFG_FUNC_1 (0x01) +#define NS9750_GPIO_CFG_FUNC_0 (0x00) + +/* the register addresses */ + +#define NS9750_BBUS_MASTER_RESET (0x00) +#define NS9750_BBUS_GPIO_CFG_BASE (0x10) +#define NS9750_BBUS_GPIO_CTRL_BASE (0x30) +#define NS9750_BBUS_GPIO_STAT_BASE (0x40) +#define NS9750_BBUS_MONITOR (0x50) +#define NS9750_BBUS_DMA_INT_STAT (0x60) +#define NS9750_BBUS_DMA_INT_ENABLE (0x64) +#define NS9750_BBUS_USB_CFG (0x70) +#define NS9750_BBUS_ENDIAN_CFG (0x80) +#define NS9750_BBUS_ARM_WAKE_UP (0x90) + +/* register bit fields */ + +#define NS9750_BBUS_MASTER_RESET_UTIL (0x00000100) +#define NS9750_BBUS_MASTER_RESET_I2C (0x00000080) +#define NS9750_BBUS_MASTER_RESET_1284 (0x00000040) +#define NS9750_BBUS_MASTER_RESET_SER4 (0x00000020) +#define NS9750_BBUS_MASTER_RESET_SER3 (0x00000010) +#define NS9750_BBUS_MASTER_RESET_SER2 (0x00000008) +#define NS9750_BBUS_MASTER_RESET_SER1 (0x00000004) +#define NS9750_BBUS_MASTER_RESET_USB (0x00000002) +#define NS9750_BBUS_MASTER_RESET_DMA (0x00000001) + +/* BS9750_BBUS_DMA_INT_BINT* are valid for *DMA_INT_STAT and *DMA_INT_ENABLE */ + +#define NS9750_BBUS_DMA_INT_BINT16 (0x00010000) +#define NS9750_BBUS_DMA_INT_BINT15 (0x00008000) +#define NS9750_BBUS_DMA_INT_BINT14 (0x00004000) +#define NS9750_BBUS_DMA_INT_BINT13 (0x00002000) +#define NS9750_BBUS_DMA_INT_BINT12 (0x00001000) +#define NS9750_BBUS_DMA_INT_BINT11 (0x00000800) +#define NS9750_BBUS_DMA_INT_BINT10 (0x00000400) +#define NS9750_BBUS_DMA_INT_BINT9 (0x00000200) +#define NS9750_BBUS_DMA_INT_BINT8 (0x00000100) +#define NS9750_BBUS_DMA_INT_BINT7 (0x00000080) +#define NS9750_BBUS_DMA_INT_BINT6 (0x00000040) +#define NS9750_BBUS_DMA_INT_BINT5 (0x00000020) +#define NS9750_BBUS_DMA_INT_BINT4 (0x00000010) +#define NS9750_BBUS_DMA_INT_BINT3 (0x00000008) +#define NS9750_BBUS_DMA_INT_BINT2 (0x00000004) +#define NS9750_BBUS_DMA_INT_BINT1 (0x00000002) +#define NS9750_BBUS_DMA_INT_BINT0 (0x00000001) + +#define NS9750_BBUS_USB_CFG_OUTEN (0x00000008) +#define NS9750_BBUS_USB_CFG_SPEED (0x00000004) +#define NS9750_BBUS_USB_CFG_CFG_MA (0x00000003) +#define NS9750_BBUS_USB_CFG_CFG_HOST_SOFT (0x00000003) +#define NS9750_BBUS_USB_CFG_CFG_DEVICE (0x00000002) +#define NS9750_BBUS_USB_CFG_CFG_HOST (0x00000001) +#define NS9750_BBUS_USB_CFG_CFG_DIS (0x00000000) + +#define NS9750_BBUS_ENDIAN_CFG_AHBM (0x00001000) +#define NS9750_BBUS_ENDIAN_CFG_I2C (0x00000080) +#define NS9750_BBUS_ENDIAN_CFG_IEEE1284 (0x00000040) +#define NS9750_BBUS_ENDIAN_CFG_SER4 (0x00000020) +#define NS9750_BBUS_ENDIAN_CFG_SER3 (0x00000010) +#define NS9750_BBUS_ENDIAN_CFG_SER2 (0x00000008) +#define NS9750_BBUS_ENDIAN_CFG_SER1 (0x00000004) +#define NS9750_BBUS_ENDIAN_CFG_USB (0x00000002) +#define NS9750_BBUS_ENDIAN_CFG_DMA (0x00000001) + +#endif /* FS_NS9750_BBUS_H */ diff --git a/include/ns9750_eth.h b/include/ns9750_eth.h new file mode 100644 index 000000000..ce0c84183 --- /dev/null +++ b/include/ns9750_eth.h @@ -0,0 +1,526 @@ +/*********************************************************************** + * + * Copyright (C) 2004 by FS Forth-Systeme GmbH. + * All rights reserved. + * + * $Id: ns9750_eth.h,v 1.2 2004/02/24 13:25:39 mpietrek Exp $ + * @Author: Markus Pietrek + * @References: [1] NS9750 Hardware Reference, December 2003 + * [2] Intel LXT971 Datasheet #249414 Rev. 02 + * [3] NS7520 Linux Ethernet Driver + * + * 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 FS_NS9750_ETH_H +#define FS_NS9750_ETH_H + +#ifdef CONFIG_DRIVER_NS9750_ETHERNET + +#define NS9750_ETH_MODULE_BASE (0xA0600000) + +#define get_eth_reg_addr(c) \ + ((volatile unsigned int*) ( NS9750_ETH_MODULE_BASE+(unsigned int) (c))) + +#define NS9750_ETH_EGCR1 (0x0000) +#define NS9750_ETH_EGCR2 (0x0004) +#define NS9750_ETH_EGSR (0x0008) +#define NS9750_ETH_FIFORX (0x000C) +#define NS9750_ETH_FIFOTX (0x0010) +#define NS9750_ETH_FIFOTXS (0x0014) +#define NS9750_ETH_ETSR (0x0018) +#define NS9750_ETH_ERSR (0x001C) +#define NS9750_ETH_MAC1 (0x0400) +#define NS9750_ETH_MAC2 (0x0404) +#define NS9750_ETH_IPGT (0x0408) +#define NS9750_ETH_IPGR (0x040C) +#define NS9750_ETH_CLRT (0x0410) +#define NS9750_ETH_MAXF (0x0414) +#define NS9750_ETH_SUPP (0x0418) +#define NS9750_ETH_TEST (0x041C) +#define NS9750_ETH_MCFG (0x0420) +#define NS9750_ETH_MCMD (0x0424) +#define NS9750_ETH_MADR (0x0428) +#define NS9750_ETH_MWTD (0x042C) +#define NS9750_ETH_MRDD (0x0430) +#define NS9750_ETH_MIND (0x0434) +#define NS9750_ETH_SA1 (0x0440) +#define NS9750_ETH_SA2 (0x0444) +#define NS9750_ETH_SA3 (0x0448) +#define NS9750_ETH_SAFR (0x0500) +#define NS9750_ETH_HT1 (0x0504) +#define NS9750_ETH_HT2 (0x0508) +#define NS9750_ETH_STAT_BASE (0x0680) +#define NS9750_ETH_RXAPTR (0x0A00) +#define NS9750_ETH_RXBPTR (0x0A04) +#define NS9750_ETH_RXCPTR (0x0A08) +#define NS9750_ETH_RXDPTR (0x0A0C) +#define NS9750_ETH_EINTR (0x0A10) +#define NS9750_ETH_EINTREN (0x0A14) +#define NS9750_ETH_TXPTR (0x0A18) +#define NS9750_ETH_TXRPTR (0x0A1C) +#define NS9750_ETH_TXERBD (0x0A20) +#define NS9750_ETH_TXSPTR (0x0A24) +#define NS9750_ETH_RXAOFF (0x0A28) +#define NS9750_ETH_RXBOFF (0x0A2C) +#define NS9750_ETH_RXCOFF (0x0A30) +#define NS9750_ETH_RXDOFF (0x0A34) +#define NS9750_ETH_TXOFF (0x0A38) +#define NS9750_ETH_RXFREE (0x0A3C) +#define NS9750_ETH_TXBD (0x1000) + +/* register bit fields */ + +#define NS9750_ETH_EGCR1_ERX (0x80000000) +#define NS9750_ETH_EGCR1_ERXDMA (0x40000000) +#define NS9750_ETH_EGCR1_ERXSHT (0x10000000) +#define NS9750_ETH_EGCR1_ERXSIZ (0x08000000) +#define NS9750_ETH_EGCR1_ETXSIZ (0x04000000) +#define NS9750_ETH_EGCR1_ETXDIAG (0x02000000) +#define NS9750_ETH_EGCR1_ERXBAD (0x01000000) +#define NS9750_ETH_EGCR1_ETX (0x00800000) +#define NS9750_ETH_EGCR1_ETXDMA (0x00400000) +#define NS9750_ETH_EGCR1_ETXWM (0x00200000) +#define NS9750_ETH_EGCR1_ERXADV (0x00100000) +#define NS9750_ETH_EGCR1_ERXINIT (0x00080000) +#define NS9750_ETH_EGCR1_PHY_MODE_MA (0x0000C000) +#define NS9750_ETH_EGCR1_PHY_MODE_MII (0x00008000) +#define NS9750_ETH_EGCR1_PHY_MODE_RMII (0x00004000) +#define NS9750_ETH_EGCR1_RXCINV (0x00001000) +#define NS9750_ETH_EGCR1_TXCINV (0x00000800) +#define NS9750_ETH_EGCR1_RXALIGN (0x00000400) +#define NS9750_ETH_EGCR1_MAC_HRST (0x00000200) +#define NS9750_ETH_EGCR1_ITXA (0x00000100) + +#define NS9750_ETH_EGCR2_TPTV_MA (0xFFFF0000) +#define NS9750_ETH_EGCR2_TPCF (0x00000040) +#define NS9750_ETH_EGCR2_THPDF (0x00000020) +#define NS9750_ETH_EGCR2_TCLER (0x00000008) +#define NS9750_ETH_EGCR2_AUTOZ (0x00000004) +#define NS9750_ETH_EGCR2_CLRCNT (0x00000002) +#define NS9750_ETH_EGCR2_STEN (0x00000001) + +#define NS9750_ETH_EGSR_RXINIT (0x00100000) +#define NS9750_ETH_EGSR_TXFIFONF (0x00080000) +#define NS9750_ETH_EGSR_TXFIFOH (0x00040000) +#define NS9750_ETH_EGSR_TXFIFOE (0x00010000) + +#define NS9750_ETH_FIFOTXS_ALL (0x00000055) +#define NS9750_ETH_FIFOTXS_3 (0x000000d5) +#define NS9750_ETH_FIFOTXS_2 (0x00000035) +#define NS9750_ETH_FIFOTXS_1 (0x0000000D) +#define NS9750_ETH_FIFOTXS_0 (0x00000003) + +#define NS9750_ETH_ETSR_TXOK (0x00008000) +#define NS9750_ETH_ETSR_TXBR (0x00004000) +#define NS9750_ETH_ETSR_TXMC (0x00002000) +#define NS9750_ETH_ETSR_TXAL (0x00001000) +#define NS9750_ETH_ETSR_TXAED (0x00000800) +#define NS9750_ETH_ETSR_TXAEC (0x00000400) +#define NS9750_ETH_ETSR_TXAUR (0x00000200) +#define NS9750_ETH_ETSR_TXAJ (0x00000100) +#define NS9750_ETH_ETSR_TXDEF (0x00000040) +#define NS9750_ETH_ETSR_TXCRC (0x00000020) +#define NS9750_ETH_ETSR_TXCOLC (0x0000000F) + +#define NS9750_ETH_ERSR_RXSIZE_MA (0x0FFF0000) +#define NS9750_ETH_ERSR_RXCE (0x00008000) +#define NS9750_ETH_ERSR_RXDV (0x00004000) +#define NS9750_ETH_ERSR_RXOK (0x00002000) +#define NS9750_ETH_ERSR_RXBR (0x00001000) +#define NS9750_ETH_ERSR_RXMC (0x00000800) +#define NS9750_ETH_ERSR_RXCRC (0x00000400) +#define NS9750_ETH_ERSR_RXDR (0x00000200) +#define NS9750_ETH_ERSR_RXCV (0x00000100) +#define NS9750_ETH_ERSR_RXSHT (0x00000040) + +#define NS9750_ETH_MAC1_SRST (0x00008000) +#define NS9750_ETH_MAC1_SIMMRST (0x00004000) +#define NS9750_ETH_MAC1_RPEMCSR (0x00000800) +#define NS9750_ETH_MAC1_RPERFUN (0x00000400) +#define NS9750_ETH_MAC1_RPEMCST (0x00000200) +#define NS9750_ETH_MAC1_RPETFUN (0x00000100) +#define NS9750_ETH_MAC1_LOOPBK (0x00000010) +#define NS9750_ETH_MAC1_TXFLOW (0x00000008) +#define NS9750_ETH_MAC1_RXFLOW (0x00000004) +#define NS9750_ETH_MAC1_PALLRX (0x00000002) +#define NS9750_ETH_MAC1_RXEN (0x00000001) + +#define NS9750_ETH_MAC2_EDEFER (0x00004000) +#define NS9750_ETH_MAC2_BACKP (0x00002000) +#define NS9750_ETH_MAC2_NOBO (0x00001000) +#define NS9750_ETH_MAC2_LONGP (0x00000200) +#define NS9750_ETH_MAC2_PUREP (0x00000100) +#define NS9750_ETH_MAC2_AUTOP (0x00000080) +#define NS9750_ETH_MAC2_VLANP (0x00000040) +#define NS9750_ETH_MAC2_PADEN (0x00000020) +#define NS9750_ETH_MAC2_CRCEN (0x00000010) +#define NS9750_ETH_MAC2_DELCRC (0x00000008) +#define NS9750_ETH_MAC2_HUGE (0x00000004) +#define NS9750_ETH_MAC2_FLENC (0x00000002) +#define NS9750_ETH_MAC2_FULLD (0x00000001) + +#define NS9750_ETH_IPGT_MA (0x0000007F) + +#define NS9750_ETH_IPGR_IPGR1 (0x00007F00) +#define NS9750_ETH_IPGR_IPGR2 (0x0000007F) + +#define NS9750_ETH_CLRT_CWIN (0x00003F00) +#define NS9750_ETH_CLRT_RETX (0x0000000F) + +#define NS9750_ETH_MAXF_MAXF (0x0000FFFF) + +#define NS9750_ETH_SUPP_RPERMII (0x00008000) +#define NS9750_ETH_SUPP_SPEED (0x00000080) + +#define NS9750_ETH_TEST_TBACK (0x00000004) +#define NS9750_ETH_TEST_TPAUSE (0x00000002) +#define NS9750_ETH_TEST_SPQ (0x00000001) + +#define NS9750_ETH_MCFG_RMIIM (0x00008000) +#define NS9750_ETH_MCFG_CLKS_MA (0x0000001C) +#define NS9750_ETH_MCFG_CLKS_4 (0x00000004) +#define NS9750_ETH_MCFG_CLKS_6 (0x00000008) +#define NS9750_ETH_MCFG_CLKS_8 (0x0000000C) +#define NS9750_ETH_MCFG_CLKS_10 (0x00000010) +#define NS9750_ETH_MCFG_CLKS_20 (0x00000014) +#define NS9750_ETH_MCFG_CLKS_30 (0x00000018) +#define NS9750_ETH_MCFG_CLKS_40 (0x0000001C) +#define NS9750_ETH_MCFG_SPRE (0x00000002) +#define NS9750_ETH_MCFG_SCANI (0x00000001) + +#define NS9750_ETH_MCMD_SCAN (0x00000002) +#define NS9750_ETH_MCMD_READ (0x00000001) + +#define NS9750_ETH_MADR_DADR_MA (0x00001F00) +#define NS9750_ETH_MADR_RADR_MA (0x0000001F) + +#define NS9750_ETH_MWTD_MA (0x0000FFFF) + +#define NS9750_ETH_MRRD_MA (0x0000FFFF) + +#define NS9750_ETH_MIND_MIILF (0x00000008) +#define NS9750_ETH_MIND_NVALID (0x00000004) +#define NS9750_ETH_MIND_SCAN (0x00000002) +#define NS9750_ETH_MIND_BUSY (0x00000001) + +#define NS9750_ETH_SA1_OCTET1_MA (0x0000FF00) +#define NS9750_ETH_SA1_OCTET2_MA (0x000000FF) + +#define NS9750_ETH_SA2_OCTET3_MA (0x0000FF00) +#define NS9750_ETH_SA2_OCTET4_MA (0x000000FF) + +#define NS9750_ETH_SA3_OCTET5_MA (0x0000FF00) +#define NS9750_ETH_SA3_OCTET6_MA (0x000000FF) + +#define NS9750_ETH_SAFR_PRO (0x00000008) +#define NS9750_ETH_SAFR_PRM (0x00000004) +#define NS9750_ETH_SAFR_PRA (0x00000002) +#define NS9750_ETH_SAFR_BROAD (0x00000001) + +#define NS9750_ETH_HT1_MA (0x0000FFFF) + +#define NS9750_ETH_HT2_MA (0x0000FFFF) + +/* also valid for EINTREN */ +#define NS9750_ETH_EINTR_RXOVL_DATA (0x02000000) +#define NS9750_ETH_EINTR_RXOVL_STAT (0x01000000) +#define NS9750_ETH_EINTR_RXBUFC (0x00800000) +#define NS9750_ETH_EINTR_RXDONEA (0x00400000) +#define NS9750_ETH_EINTR_RXDONEB (0x00200000) +#define NS9750_ETH_EINTR_RXDONEC (0x00100000) +#define NS9750_ETH_EINTR_RXDONED (0x00080000) +#define NS9750_ETH_EINTR_RXNOBUF (0x00040000) +#define NS9750_ETH_EINTR_RXBUFFUL (0x00020000) +#define NS9750_ETH_EINTR_RXBR (0x00010000) +#define NS9750_ETH_EINTR_STOVFL (0x00000040) +#define NS9750_ETH_EINTR_TXPAUSE (0x00000020) +#define NS9750_ETH_EINTR_TXBUFC (0x00000010) +#define NS9750_ETH_EINTR_TXBUFNR (0x00000008) +#define NS9750_ETH_EINTR_TXDONE (0x00000004) +#define NS9750_ETH_EINTR_TXERR (0x00000002) +#define NS9750_ETH_EINTR_TXIDLE (0x00000001) +#define NS9750_ETH_EINTR_RX_MA \ + (NS9750_ETH_EINTR_RXOVL_DATA | \ + NS9750_ETH_EINTR_RXOVL_STAT | \ + NS9750_ETH_EINTR_RXBUFC | \ + NS9750_ETH_EINTR_RXDONEA | \ + NS9750_ETH_EINTR_RXDONEB | \ + NS9750_ETH_EINTR_RXDONEC | \ + NS9750_ETH_EINTR_RXDONED | \ + NS9750_ETH_EINTR_RXNOBUF | \ + NS9750_ETH_EINTR_RXBUFFUL | \ + NS9750_ETH_EINTR_RXBR ) +#define NS9750_ETH_EINTR_TX_MA \ + (NS9750_ETH_EINTR_TXPAUSE | \ + NS9750_ETH_EINTR_TXBUFC | \ + NS9750_ETH_EINTR_TXBUFNR | \ + NS9750_ETH_EINTR_TXDONE | \ + NS9750_ETH_EINTR_TXERR | \ + NS9750_ETH_EINTR_TXIDLE) + +/* for TXPTR, TXRPTR, TXERBD and TXSPTR */ +#define NS9750_ETH_TXPTR_MA (0x000000FF) + +/* for RXAOFF, RXBOFF, RXCOFF and RXDOFF */ +#define NS9750_ETH_RXOFF_MA (0x000007FF) + +#define NS9750_ETH_TXOFF_MA (0x000003FF) + +#define NS9750_ETH_RXFREE_D (0x00000008) +#define NS9750_ETH_RXFREE_C (0x00000004) +#define NS9750_ETH_RXFREE_B (0x00000002) +#define NS9750_ETH_RXFREE_A (0x00000001) + +/* PHY definitions (LXT971A) [2] */ + +#define PHY_COMMON_CTRL (0x00) +#define PHY_COMMON_STAT (0x01) +#define PHY_COMMON_ID1 (0x02) +#define PHY_COMMON_ID2 (0x03) +#define PHY_COMMON_AUTO_ADV (0x04) +#define PHY_COMMON_AUTO_LNKB (0x05) +#define PHY_COMMON_AUTO_EXP (0x06) +#define PHY_COMMON_AUTO_NEXT (0x07) +#define PHY_COMMON_AUTO_LNKN (0x08) +#define PHY_LXT971_PORT_CFG (0x10) +#define PHY_LXT971_STAT2 (0x11) +#define PHY_LXT971_INT_ENABLE (0x12) +#define PHY_LXT971_INT_STATUS (0x13) +#define PHY_LXT971_LED_CFG (0x14) +#define PHY_LXT971_DIG_CFG (0x1A) +#define PHY_LXT971_TX_CTRL (0x1E) + +/* CTRL PHY Control Register Bit Fields */ + +#define PHY_COMMON_CTRL_RESET (0x8000) +#define PHY_COMMON_CTRL_LOOPBACK (0x4000) +#define PHY_COMMON_CTRL_SPD_MA (0x2040) +#define PHY_COMMON_CTRL_SPD_10 (0x0000) +#define PHY_COMMON_CTRL_SPD_100 (0x2000) +#define PHY_COMMON_CTRL_SPD_1000 (0x0040) +#define PHY_COMMON_CTRL_SPD_RES (0x2040) +#define PHY_COMMON_CTRL_AUTO_NEG (0x1000) +#define PHY_COMMON_CTRL_POWER_DN (0x0800) +#define PHY_COMMON_CTRL_ISOLATE (0x0400) +#define PHY_COMMON_CTRL_RES_AUTO (0x0200) +#define PHY_COMMON_CTRL_DUPLEX (0x0100) +#define PHY_COMMON_CTRL_COL_TEST (0x0080) +#define PHY_COMMON_CTRL_RES1 (0x003F) + +/* STAT Status Register Bit Fields */ + +#define PHY_COMMON_STAT_100BT4 (0x8000) +#define PHY_COMMON_STAT_100BXFD (0x4000) +#define PHY_COMMON_STAT_100BXHD (0x2000) +#define PHY_COMMON_STAT_10BTFD (0x1000) +#define PHY_COMMON_STAT_10BTHD (0x0800) +#define PHY_COMMON_STAT_100BT2FD (0x0400) +#define PHY_COMMON_STAT_100BT2HD (0x0200) +#define PHY_COMMON_STAT_EXT_STAT (0x0100) +#define PHY_COMMON_STAT_RES1 (0x0080) +#define PHY_COMMON_STAT_MF_PSUP (0x0040) +#define PHY_COMMON_STAT_AN_COMP (0x0020) +#define PHY_COMMON_STAT_RMT_FLT (0x0010) +#define PHY_COMMON_STAT_AN_CAP (0x0008) +#define PHY_COMMON_STAT_LNK_STAT (0x0004) +#define PHY_COMMON_STAT_JAB_DTCT (0x0002) +#define PHY_COMMON_STAT_EXT_CAP (0x0001) + + +/* AUTO_ADV Auto-neg Advert Register Bit Fields */ + +#define PHY_COMMON_AUTO_ADV_NP (0x8000) +#define PHY_COMMON_AUTO_ADV_RES1 (0x4000) +#define PHY_COMMON_AUTO_ADV_RMT_FLT (0x2000) +#define PHY_COMMON_AUTO_ADV_RES2 (0x1000) +#define PHY_COMMON_AUTO_ADV_AS_PAUSE (0x0800) +#define PHY_COMMON_AUTO_ADV_PAUSE (0x0400) +#define PHY_COMMON_AUTO_ADV_100BT4 (0x0200) +#define PHY_COMMON_AUTO_ADV_100BTXFD (0x0100) +#define PHY_COMMON_AUTO_ADV_100BTX (0x0080) +#define PHY_COMMON_AUTO_ADV_10BTFD (0x0040) +#define PHY_COMMON_AUTO_ADV_10BT (0x0020) +#define PHY_COMMON_AUTO_ADV_SEL_FLD_MA (0x001F) +#define PHY_COMMON_AUTO_ADV_802_9 (0x0002) +#define PHY_COMMON_AUTO_ADV_802_3 (0x0001) + +/* AUTO_LNKB Auto-neg Link Ability Register Bit Fields */ + +#define PHY_COMMON_AUTO_LNKB_NP (0x8000) +#define PHY_COMMON_AUTO_LNKB_ACK (0x4000) +#define PHY_COMMON_AUTO_LNKB_RMT_FLT (0x2000) +#define PHY_COMMON_AUTO_LNKB_RES2 (0x1000) +#define PHY_COMMON_AUTO_LNKB_AS_PAUSE (0x0800) +#define PHY_COMMON_AUTO_LNKB_PAUSE (0x0400) +#define PHY_COMMON_AUTO_LNKB_100BT4 (0x0200) +#define PHY_COMMON_AUTO_LNKB_100BTXFD (0x0100) +#define PHY_COMMON_AUTO_LNKB_100BTX (0x0080) +#define PHY_COMMON_AUTO_LNKB_10BTFD (0x0040) +#define PHY_COMMON_AUTO_LNKB_10BT (0x0020) +#define PHY_COMMON_AUTO_LNKB_SEL_FLD_MA (0x001F) +#define PHY_COMMON_AUTO_LNKB_802_9 (0x0002) +#define PHY_COMMON_AUTO_LNKB_802_3 (0x0001) + +/* AUTO_EXP Auto-neg Expansion Register Bit Fields */ + +#define PHY_COMMON_AUTO_EXP_RES1 (0xFFC0) +#define PHY_COMMON_AUTO_EXP_BASE_PAGE (0x0020) +#define PHY_COMMON_AUTO_EXP_PAR_DT_FLT (0x0010) +#define PHY_COMMON_AUTO_EXP_LNK_NP_CAP (0x0008) +#define PHY_COMMON_AUTO_EXP_NP_CAP (0x0004) +#define PHY_COMMON_AUTO_EXP_PAGE_REC (0x0002) +#define PHY_COMMON_AUTO_EXP_LNK_AN_CAP (0x0001) + +/* AUTO_NEXT Aut-neg Next Page Tx Register Bit Fields */ + +#define PHY_COMMON_AUTO_NEXT_NP (0x8000) +#define PHY_COMMON_AUTO_NEXT_RES1 (0x4000) +#define PHY_COMMON_AUTO_NEXT_MSG_PAGE (0x2000) +#define PHY_COMMON_AUTO_NEXT_ACK_2 (0x1000) +#define PHY_COMMON_AUTO_NEXT_TOGGLE (0x0800) +#define PHY_COMMON_AUTO_NEXT_MSG (0x07FF) + +/* AUTO_LNKN Auto-neg Link Partner Rx Reg Bit Fields */ + +#define PHY_COMMON_AUTO_LNKN_NP (0x8000) +#define PHY_COMMON_AUTO_LNKN_ACK (0x4000) +#define PHY_COMMON_AUTO_LNKN_MSG_PAGE (0x2000) +#define PHY_COMMON_AUTO_LNKN_ACK_2 (0x1000) +#define PHY_COMMON_AUTO_LNKN_TOGGLE (0x0800) +#define PHY_COMMON_AUTO_LNKN_MSG (0x07FF) + +/* PORT_CFG Port Configuration Register Bit Fields */ + +#define PHY_LXT971_PORT_CFG_RES1 (0x8000) +#define PHY_LXT971_PORT_CFG_FORCE_LNK (0x4000) +#define PHY_LXT971_PORT_CFG_TX_DISABLE (0x2000) +#define PHY_LXT971_PORT_CFG_BYPASS_SCR (0x1000) +#define PHY_LXT971_PORT_CFG_RES2 (0x0800) +#define PHY_LXT971_PORT_CFG_JABBER (0x0400) +#define PHY_LXT971_PORT_CFG_SQE (0x0200) +#define PHY_LXT971_PORT_CFG_TP_LOOPBACK (0x0100) +#define PHY_LXT971_PORT_CFG_CRS_SEL (0x0080) +#define PHY_LXT971_PORT_CFG_SLEEP_MODE (0x0040) +#define PHY_LXT971_PORT_CFG_PRE_EN (0x0020) +#define PHY_LXT971_PORT_CFG_SLEEP_T_MA (0x0018) +#define PHY_LXT971_PORT_CFG_SLEEP_T_104 (0x0010) +#define PHY_LXT971_PORT_CFG_SLEEP_T_200 (0x0001) +#define PHY_LXT971_PORT_CFG_SLEEP_T_304 (0x0000) +#define PHY_LXT971_PORT_CFG_FLT_CODE_EN (0x0004) +#define PHY_LXT971_PORT_CFG_ALT_NP (0x0002) +#define PHY_LXT971_PORT_CFG_FIBER_SEL (0x0001) + +/* STAT2 Status Register #2 Bit Fields */ + +#define PHY_LXT971_STAT2_RES1 (0x8000) +#define PHY_LXT971_STAT2_100BTX (0x4000) +#define PHY_LXT971_STAT2_TX_STATUS (0x2000) +#define PHY_LXT971_STAT2_RX_STATUS (0x1000) +#define PHY_LXT971_STAT2_COL_STATUS (0x0800) +#define PHY_LXT971_STAT2_LINK (0x0400) +#define PHY_LXT971_STAT2_DUPLEX_MODE (0x0200) +#define PHY_LXT971_STAT2_AUTO_NEG (0x0100) +#define PHY_LXT971_STAT2_AUTO_NEG_COMP (0x0080) +#define PHY_LXT971_STAT2_RES2 (0x0040) +#define PHY_LXT971_STAT2_POLARITY (0x0020) +#define PHY_LXT971_STAT2_PAUSE (0x0010) +#define PHY_LXT971_STAT2_ERROR (0x0008) +#define PHY_LXT971_STAT2_RES3 (0x0007) + +/* INT_ENABLE Interrupt Enable Register Bit Fields */ + +#define PHY_LXT971_INT_ENABLE_RES1 (0xFF00) +#define PHY_LXT971_INT_ENABLE_ANMSK (0x0080) +#define PHY_LXT971_INT_ENABLE_SPEEDMSK (0x0040) +#define PHY_LXT971_INT_ENABLE_DUPLEXMSK (0x0020) +#define PHY_LXT971_INT_ENABLE_LINKMSK (0x0010) +#define PHY_LXT971_INT_ENABLE_RES2 (0x000C) +#define PHY_LXT971_INT_ENABLE_INTEN (0x0002) +#define PHY_LXT971_INT_ENABLE_TINT (0x0001) + +/* INT_STATUS Interrupt Status Register Bit Fields */ + +#define PHY_LXT971_INT_STATUS_RES1 (0xFF00) +#define PHY_LXT971_INT_STATUS_ANDONE (0x0080) +#define PHY_LXT971_INT_STATUS_SPEEDCHG (0x0040) +#define PHY_LXT971_INT_STATUS_DUPLEXCHG (0x0020) +#define PHY_LXT971_INT_STATUS_LINKCHG (0x0010) +#define PHY_LXT971_INT_STATUS_RES2 (0x0008) +#define PHY_LXT971_INT_STATUS_MDINT (0x0004) +#define PHY_LXT971_INT_STATUS_RES3 (0x0003) + +/* LED_CFG Interrupt LED Configuration Register Bit Fields */ + +#define PHY_LXT971_LED_CFG_SHIFT_LED1 (0x000C) +#define PHY_LXT971_LED_CFG_SHIFT_LED2 (0x0008) +#define PHY_LXT971_LED_CFG_SHIFT_LED3 (0x0004) +#define PHY_LXT971_LED_CFG_LEDFREQ_MA (0x000C) +#define PHY_LXT971_LED_CFG_LEDFREQ_RES (0x000C) +#define PHY_LXT971_LED_CFG_LEDFREQ_100 (0x0008) +#define PHY_LXT971_LED_CFG_LEDFREQ_60 (0x0004) +#define PHY_LXT971_LED_CFG_LEDFREQ_30 (0x0000) +#define PHY_LXT971_LED_CFG_PULSE_STR (0x0002) +#define PHY_LXT971_LED_CFG_RES1 (0x0001) + +/* only one of these values must be shifted for each SHIFT_LED? */ + +#define PHY_LXT971_LED_CFG_UNUSED1 (0x000F) +#define PHY_LXT971_LED_CFG_DUPLEX_COL (0x000E) +#define PHY_LXT971_LED_CFG_LINK_ACT (0x000D) +#define PHY_LXT971_LED_CFG_LINK_RX (0x000C) +#define PHY_LXT971_LED_CFG_TEST_BLK_SLW (0x000B) +#define PHY_LXT971_LED_CFG_TEST_BLK_FST (0x000A) +#define PHY_LXT971_LED_CFG_TEST_OFF (0x0009) +#define PHY_LXT971_LED_CFG_TEST_ON (0x0008) +#define PHY_LXT971_LED_CFG_RX_OR_TX (0x0007) +#define PHY_LXT971_LED_CFG_UNUSED2 (0x0006) +#define PHY_LXT971_LED_CFG_DUPLEX (0x0005) +#define PHY_LXT971_LED_CFG_LINK (0x0004) +#define PHY_LXT971_LED_CFG_COLLISION (0x0003) +#define PHY_LXT971_LED_CFG_RECEIVE (0x0002) +#define PHY_LXT971_LED_CFG_TRANSMIT (0x0001) +#define PHY_LXT971_LED_CFG_SPEED (0x0000) + +/* DIG_CFG Digitial Configuration Register Bit Fields */ + +#define PHY_LXT971_DIG_CFG_RES1 (0xF000) +#define PHY_LXT971_DIG_CFG_MII_DRIVE (0x0800) +#define PHY_LXT971_DIG_CFG_RES2 (0x0400) +#define PHY_LXT971_DIG_CFG_SHOW_SYMBOL (0x0200) +#define PHY_LXT971_DIG_CFG_RES3 (0x01FF) + +#define PHY_LXT971_MDIO_MAX_CLK (8000000) + +/* TX_CTRL Transmit Control Register Bit Fields + documentation is buggy for this register, therefore setting not included */ + +typedef enum +{ + PHY_NONE = 0x0000, /* no PHY detected yet */ + PHY_LXT971A = 0x0013 +} PhyType; + +#define PHY_MDIO_MAX_CLK (2500000) + +#ifndef NS9750_ETH_PHY_ADDRESS +# define NS9750_ETH_PHY_ADDRESS (0x0001) /* suitable for UNC20 */ +#endif /* NETARM_ETH_PHY_ADDRESS */ + +#endif /* CONFIG_DRIVER_NS9750_ETHERNET */ + +#endif /* FS_NS9750_ETH_H */ diff --git a/include/ns9750_mem.h b/include/ns9750_mem.h new file mode 100644 index 000000000..44c8ddcdd --- /dev/null +++ b/include/ns9750_mem.h @@ -0,0 +1,172 @@ +/*********************************************************************** + * + * Copyright (C) 2004 by FS Forth-Systeme GmbH. + * All rights reserved. + * + * $Id: ns9750_mem.h,v 1.1 2004/02/16 10:37:20 mpietrek Exp $ + * @Author: Markus Pietrek + * @Descr: Definitions for Memory Control Module + * @References: [1] NS9750 Hardware Reference Manual/December 2003 Chap. 5 + * + * 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 FS_NS9750_MEM_H +#define FS_NS9750_SYS_H + +#define NS9750_MEM_MODULE_BASE (0xA0700000) + +#define get_mem_reg_addr(c) \ + ((volatile unsigned int *)(NS9750_MEM_MODULE_BASE+(unsigned int) (c))) + +/* the register addresses */ + +#define NS9750_MEM_CTRL (0x0000) +#define NS9750_MEM_STATUS (0x0004) +#define NS9750_MEM_CFG (0x0008) +#define NS9750_MEM_DYN_CTRL (0x0020) +#define NS9750_MEM_DYN_REFRESH (0x0024) +#define NS9750_MEM_DYN_READ_CFG (0x0028) +#define NS9750_MEM_DYN_TRP (0x0030) +#define NS9750_MEM_DYN_TRAS (0x0034) +#define NS9750_MEM_DYN_TSREX (0x0038) +#define NS9750_MEM_DYN_TAPR (0x003C) +#define NS9750_MEM_DYN_TDAL (0x0040) +#define NS9750_MEM_DYN_TWR (0x0044) +#define NS9750_MEM_DYN_TRC (0x0048) +#define NS9750_MEM_DYN_TRFC (0x004C) +#define NS9750_MEM_DYN_TXSR (0x0050) +#define NS9750_MEM_DYN_TRRD (0x0054) +#define NS9750_MEM_DYN_TMRD (0x0058) +#define NS9750_MEM_STAT_EXT_WAIT (0x0080) +#define NS9750_MEM_DYN_CFG_BASE (0x0100) +#define NS9750_MEM_DYN_RAS_CAS_BASE (0x0104) +#define NS9750_MEM_STAT_CFG_BASE (0x0200) +#define NS9750_MEM_STAT_WAIT_WEN_BASE (0x0204) +#define NS9750_MEM_STAT_WAIT_OEN_BASE (0x0208) +#define NS9750_MEM_STAT_WAIT_RD_BASE (0x020C) +#define NS9750_MEM_STAT_WAIT_PAGE_BASE (0x0210) +#define NS9750_MEM_STAT_WAIR_WR_BASE (0x0214) +#define NS9750_MEM_STAT_WAIT_TURN_BASE (0x0218) + +/* the vectored register addresses */ + +#define NS9750_MEM_DYN_CFG(c) (NS9750_MEM_DYN_CFG_BASE + (c)*0x20) +#define NS9750_MEM_DYN_RAS_CAS(c) (NS9750_MEM_DYN_RAS_CAS_BASE + (c)*0x20) +#define NS9750_MEM_STAT_CFG(c) (NS9750_MEM_STAT_CFG_BASE + (c)*0x20) +#define NS9750_MEM_STAT_WAIT_WEN(c) (NS9750_MEM_STAT_WAIT_WEN_BASE+(c)*0x20) +#define NS9750_MEM_STAT_WAIT_OEN(c) (NS9750_MEM_STAT_WAIT_OEN_BASE+(c)*0x20) +#define NS9750_MEM_STAT_RD(c) (NS9750_MEM_STAT_WAIT_RD_BASE+(c)*0x20) +#define NS9750_MEM_STAT_PAGE(c) (NS9750_MEM_STAT_WAIT_PAGE_BASE+(c)*0x20) +#define NS9750_MEM_STAT_WR(c) (NS9750_MEM_STAT_WAIT_WR_BASE+(c)*0x20) +#define NS9750_MEM_STAT_TURN(c) (NS9750_MEM_STAT_WAIT_TURN_BASE+(c)*0x20) + +/* register bit fields */ + +#define NS9750_MEM_CTRL_L (0x00000004) +#define NS9750_MEM_CTRL_M (0x00000002) +#define NS9750_MEM_CTRL_E (0x00000001) + +#define NS9750_MEM_STAT_SA (0x00000004) +#define NS9750_MEM_STAT_S (0x00000002) +#define NS9750_MEM_STAT_B (0x00000001) + +#define NS9750_MEM_CFG_CLK (0x00000010) +#define NS9750_MEM_CFG_N (0x00000001) + +#define NS9750_MEM_DYN_CTRL_NRP (0x00004000) +#define NS9750_MEM_DYN_CTRL_DP (0x00002000) +#define NS9750_MEM_DYN_CTRL_I_MA (0x00000180) +#define NS9750_MEM_DYN_CTRL_I_NORMAL (0x00000000) +#define NS9750_MEM_DYN_CTRL_I_MODE (0x00000080) +#define NS9750_MEM_DYN_CTRL_I_PALL (0x00000100) +#define NS9750_MEM_DYN_CTRL_I_NOP (0x00000180) +#define NS9750_MEM_DYN_CTRL_SR (0x00000002) +#define NS9750_MEM_DYN_CTRL_CE (0x00000001) + + +#define NS9750_MEM_DYN_REFRESH_MA (0x000007FF) + +#define NS9750_MEM_DYN_READ_CFG_MA (0x00000003) +#define NS9750_MEM_DYN_READ_CFG_DELAY0 (0x00000001) +#define NS9750_MEM_DYN_READ_CFG_DELAY1 (0x00000002) +#define NS9750_MEM_DYN_READ_CFG_DELAY2 (0x00000003) + +#define NS9750_MEM_DYN_TRP_MA (0x0000000F) + +#define NS9750_MEM_DYN_TRAS_MA (0x0000000F) + +#define NS9750_MEM_DYN_TSREX_MA (0x0000000F) + +#define NS9750_MEM_DYN_TAPR_MA (0x0000000F) + +#define NS9750_MEM_DYN_TDAL_MA (0x0000000F) + +#define NS9750_MEM_DYN_TWR_MA (0x0000000F) + +#define NS9750_MEM_DYN_TRC_MA (0x0000001F) + +#define NS9750_MEM_DYN_TRFC_MA (0x0000001F) + +#define NS9750_MEM_DYN_TXSR_MA (0x0000001F) + +#define NS9750_MEM_DYN_TRRD_MA (0x0000000F) + +#define NS9750_MEM_DYN_TMRD_MA (0x0000000F) + +#define NS9750_MEM_STAT_EXTW_WAIT_MA (0x0000003F) + +#define NS9750_MEM_DYN_CFG_P (0x00100000) +#define NS9750_MEM_DYN_CFG_BDMC (0x00080000) +#define NS9750_MEM_DYN_CFG_AM (0x00004000) +#define NS9750_MEM_DYN_CFG_AM_MA (0x00001F80) +#define NS9750_MEM_DYN_CFG_MD (0x00000018) + +#define NS9750_MEM_DYN_RAS_CAS_CAS_MA (0x00000300) +#define NS9750_MEM_DYN_RAS_CAS_CAS_1 (0x00000100) +#define NS9750_MEM_DYN_RAS_CAS_CAS_2 (0x00000200) +#define NS9750_MEM_DYN_RAS_CAS_CAS_3 (0x00000300) +#define NS9750_MEM_DYN_RAS_CAS_RAS_MA (0x00000003) +#define NS9750_MEM_DYN_RAS_CAS_RAS_1 (0x00000001) +#define NS9750_MEM_DYN_RAS_CAS_RAS_2 (0x00000002) +#define NS9750_MEM_DYN_RAS_CAS_RAS_3 (0x00000003) + +#define NS9750_MEM_STAT_CFG_PSMC (0x00100000) +#define NS9750_MEM_STAT_CFG_BSMC (0x00080000) +#define NS9750_MEM_STAT_CFG_EW (0x00000100) +#define NS9750_MEM_STAT_CFG_PB (0x00000080) +#define NS9750_MEM_STAT_CFG_PC (0x00000040) +#define NS9750_MEM_STAT_CFG_PM (0x00000008) +#define NS9750_MEM_STAT_CFG_MW_MA (0x00000003) +#define NS9750_MEM_STAT_CFG_MW_8 (0x00000000) +#define NS9750_MEM_STAT_CFG_MW_16 (0x00000001) +#define NS9750_MEM_STAT_CFG_MW_32 (0x00000002) + +#define NS9750_MEM_STAT_WAIT_WEN_MA (0x0000000F) + +#define NS9750_MEM_STAT_WAIT_OEN_MA (0x0000000F) + +#define NS9750_MEM_STAT_WAIT_RD_MA (0x0000001F) + +#define NS9750_MEM_STAT_WAIT_PAGE_MA (0x0000001F) + +#define NS9750_MEM_STAT_WAIT_WR_MA (0x0000001F) + +#define NS9750_MEM_STAT_WAIT_TURN_MA (0x0000000F) + + +#endif /* FS_NS9750_MEM_H */ diff --git a/include/ns9750_ser.h b/include/ns9750_ser.h new file mode 100644 index 000000000..e6ff3e172 --- /dev/null +++ b/include/ns9750_ser.h @@ -0,0 +1,202 @@ +/*********************************************************************** + * + * Copyright (C) 2004 by FS Forth-Systeme GmbH. + * All rights reserved. + * + * $Id: ns9750_ser.h,v 1.1 2004/02/16 10:37:20 mpietrek Exp $ + * @Author: Markus Pietrek + * @References: [1] NS9750 Hardware Reference, December 2003 + * + * 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 FS_NS9750_SER_H +#define FS_NS9750_SER_H + +#define NS9750_SER_MODULE_BASE (0x90200000) + +#define get_ser_reg_addr(c) \ + ((volatile unsigned int *)(NS9750_SER_MODULE_BASE+(unsigned int) (c))) + +#define get_ser_reg_addr_channel(reg,chan) \ + get_ser_reg_addr((reg)+(((chan)<2)?0:0x00100000)+(((chan)&1)?0x40:0)) + +/* the register addresses */ + +#define NS9750_SER_CTRL_A (0x00) +#define NS9750_SER_CTRL_B (0x04) +#define NS9750_SER_STAT_A (0x08) +#define NS9750_SER_BITRATE (0x0C) +#define NS9750_SER_FIFO (0x10) +#define NS9750_SER_RX_BUF_TIMER (0x14) +#define NS9750_SER_RX_CHAR_TIMER (0x18) +#define NS9750_SER_RX_MATCH (0x1C) +#define NS9750_SER_RX_MATCH_MASK (0x20) +#define NS9750_SER_FLOW_CTRL (0x34) +#define NS9750_SER_FLOW_CTRL_FORCE (0x38) + +/* register bit fields */ + +/* control A register */ + +#define NS9750_SER_CTRL_A_CE (0x80000000) +#define NS9750_SER_CTRL_A_BRK (0x40000000) +#define NS9750_SER_CTRL_A_STICKP (0x20000000) +#define NS9750_SER_CTRL_A_EPS (0x10000000) +#define NS9750_SER_CTRL_A_PE (0x08000000) +#define NS9750_SER_CTRL_A_STOP (0x04000000) +#define NS9750_SER_CTRL_A_WLS_MA (0x03000000) +#define NS9750_SER_CTRL_A_WLS_5 (0x00000000) +#define NS9750_SER_CTRL_A_WLS_6 (0x01000000) +#define NS9750_SER_CTRL_A_WLS_7 (0x02000000) +#define NS9750_SER_CTRL_A_WLS_8 (0x03000000) +#define NS9750_SER_CTRL_A_CTSTX (0x00800000) +#define NS9750_SER_CTRL_A_RTSRX (0x00400000) +#define NS9750_SER_CTRL_A_RL (0x00200000) +#define NS9750_SER_CTRL_A_LL (0x00100000) +#define NS9750_SER_CTRL_A_RES (0x000CF000) +#define NS9750_SER_CTRL_A_DTR (0x00020000) +#define NS9750_SER_CTRL_A_RTS (0x00010000) +#define NS9750_SER_CTRL_A_RIE_MA (0x00000E00) +#define NS9750_SER_CTRL_A_ERXDMA (0x00000100) +#define NS9750_SER_CTRL_A_RIC_MA (0x000000E0) +#define NS9750_SER_CTRL_A_TIC_MA (0x0000001E) +#define NS9750_SER_CTRL_A_ETXDMA (0x00000001) + +/* control B register */ + +#define NS9750_SER_CTRL_B_RDM1 (0x80000000) +#define NS9750_SER_CTRL_B_RDM2 (0x40000000) +#define NS9750_SER_CTRL_B_RDM3 (0x20000000) +#define NS9750_SER_CTRL_B_RDM4 (0x10000000) +#define NS9750_SER_CTRL_B_RBGT (0x08000000) +#define NS9750_SER_CTRL_B_RCGT (0x04000000) +#define NS9750_SER_CTRL_B_MODE_MA (0x00300000) +#define NS9750_SER_CTRL_B_MODE_UART (0x00000000) +#define NS9750_SER_CTRL_B_MODE_HDLC (0x00100000) +#define NS9750_SER_CTRL_B_MODE_SPI_M (0x00200000) +#define NS9750_SER_CTRL_B_MODE_SPI_S (0x00300000) +#define NS9750_SER_CTRL_B_BITORDR (0x00080000) +#define NS9750_SER_CTRL_B_RES (0x0007703F) +#define NS9750_SER_CTRL_B_RTSTX (0x00008000) +#define NS9750_SER_CTRL_B_ENDEC_MA (0x00000FC0) + +/* status A register */ + +#define NS9750_SER_STAT_A_MATCH1 (0x80000000) +#define NS9750_SER_STAT_A_MATCH2 (0x40000000) +#define NS9750_SER_STAT_A_MATCH3 (0x20000000) +#define NS9750_SER_STAT_A_MATCH4 (0x10000000) +#define NS9750_SER_STAT_A_BGAP (0x08000000) +#define NS9750_SER_STAT_A_CGAP (0x04000000) +#define NS9750_SER_STAT_A_RXFDB_MA (0x00300000) +#define NS9750_SER_STAT_A_RXFDB_FULL (0x00000000) +#define NS9750_SER_STAT_A_RXFDB_1 (0x00100000) +#define NS9750_SER_STAT_A_RXFDB_2 (0x00200000) +#define NS9750_SER_STAT_A_RXFDB_3 (0x00300000) +#define NS9750_SER_STAT_A_DCD (0x00080000) +#define NS9750_SER_STAT_A_RI (0x00040000) +#define NS9750_SER_STAT_A_DSR (0x00020000) +#define NS9750_SER_STAT_A_CTS (0x00010000) +#define NS9750_SER_STAT_A_RBRK (0x00008000) +#define NS9750_SER_STAT_A_RFE (0x00004000) +#define NS9750_SER_STAT_A_RPE (0x00002000) +#define NS9750_SER_STAT_A_ROVER (0x00001000) +#define NS9750_SER_STAT_A_RRDY (0x00000800) +#define NS9750_SER_STAT_A_RHALF (0x00000400) +#define NS9750_SER_STAT_A_RBC (0x00000200) +#define NS9750_SER_STAT_A_RFULL (0x00000100) +#define NS9750_SER_STAT_A_DCDI (0x00000080) +#define NS9750_SER_STAT_A_RII (0x00000040) +#define NS9750_SER_STAT_A_DSRI (0x00000020) +#define NS9750_SER_STAT_A_CTSI (0x00000010) +#define NS9750_SER_STAT_A_TRDY (0x00000008) +#define NS9750_SER_STAT_A_THALF (0x00000004) +#define NS9750_SER_STAT_A_TBC (0x00000002) +#define NS9750_SER_STAT_A_TEMPTY (0x00000001) + +#define NS9750_SER_STAT_A_RX_COND_ERR ( NS9750_SER_STAT_A_RFE | \ + NS9750_SER_STAT_A_ROVER | \ + NS9750_SER_STAT_A_RPE ) +#define NS9750_SER_STAT_A_RX_COND_ALL ( NS9750_SER_STAT_A_RX_COND_ERR | \ + NS9750_SER_STAT_A_RBRK | \ + NS9750_SER_STAT_A_RRDY | \ + NS9750_SER_STAT_A_RHALF | \ + NS9750_SER_STAT_A_RBC | \ + NS9750_SER_STAT_A_DCDI | \ + NS9750_SER_STAT_A_RII | \ + NS9750_SER_STAT_A_DSRI | \ + NS9750_SER_STAT_A_CTSI ) +#define NS9750_SER_STAT_A_TX_COND_ALL ( NS9750_SER_STAT_A_TRDY | \ + NS9750_SER_STAT_A_THALF | \ + NS9750_SER_STAT_A_TBC | \ + NS9750_SER_STAT_A_TEMPTY ) +/* bit rate register */ + +#define NS9750_SER_BITRATE_EBIT (0x80000000) +#define NS9750_SER_BITRATE_TMODE (0x40000000) +#define NS9750_SER_BITRATE_RXSRC (0x20000000) +#define NS9750_SER_BITRATE_TXSRC (0x10000000) +#define NS9750_SER_BITRATE_RXEXT (0x08000000) +#define NS9750_SER_BITRATE_TXEXT (0x04000000) +#define NS9750_SER_BITRATE_CLKMUX_MA (0x03000000) +#define NS9750_SER_BITRATE_CLKMUX_XTAL (0x00000000) +#define NS9750_SER_BITRATE_CLKMUX_BCLK (0x01000000) +#define NS9750_SER_BITRATE_CLKMUX_OUT1 (0x02000000) +#define NS9750_SER_BITRATE_CLKMUX_OUT2 (0x03000000) +#define NS9750_SER_BITRATE_TXCINV (0x00800000) +#define NS9750_SER_BITRATE_RXCINV (0x00400000) +#define NS9750_SER_BITRATE_TCDR_MA (0x00180000) +#define NS9750_SER_BITRATE_TCDR_1 (0x00000000) +#define NS9750_SER_BITRATE_TCDR_8 (0x00080000) +#define NS9750_SER_BITRATE_TCDR_16 (0x00100000) +#define NS9750_SER_BITRATE_TCDR_32 (0x00180000) +#define NS9750_SER_BITRATE_RCDR_MA (0x00070000) +#define NS9750_SER_BITRATE_RCDR_1 (0x00000000) +#define NS9750_SER_BITRATE_RCDR_8 (0x00020000) +#define NS9750_SER_BITRATE_RCDR_16 (0x00040000) +#define NS9750_SER_BITRATE_RCDR_32 (0x00060000) +#define NS9750_SER_BITRATE_TICS (0x00010000) +#define NS9750_SER_BITRATE_RICS (0x00008000) +#define NS9750_SER_BITRATE_N_MA (0x00007FFF) + +/* receive buffer gap timer */ + +#define NS9750_SER_RX_BUF_TIMER_TRUN (0x80000000) /* UART and SPI */ +#define NS9750_SER_RX_BUF_TIMER_BT_MA (0x0000FFFF) /* UART and SPI */ +#define NS9750_SER_RX_BUF_TIMER_MAXLEN_MA (0x0000FFFF) /* HDLC only */ + +/* receive character gap timer */ + +#define NS9750_SER_RX_CHAR_TIMER_TRUN (0x80000000) +#define NS9750_SER_RX_CHAR_TIMER_CT_MA (0x000FFFFF) + +/* receive match */ + +#define NS9750_SER_RX_MATCH_RDMB1_MA (0xFF000000) +#define NS9750_SER_RX_MATCH_RDMB2_MA (0x00FF0000) +#define NS9750_SER_RX_MATCH_RDMB3_MA (0x0000FF00) +#define NS9750_SER_RX_MATCH_RDMB4_MA (0x000000FF) + +/* receive match mask */ + +#define NS9750_SER_RX_MATCH_MASK_RDMB1_MA (0xFF000000) +#define NS9750_SER_RX_MATCH_MASK_RDMB2_MA (0x00FF0000) +#define NS9750_SER_RX_MATCH_MASK_RDMB3_MA (0x0000FF00) +#define NS9750_SER_RX_MATCH_MASK_RDMB4_MA (0x000000FF) + +#endif /* FS_NS9750_SER_H */ diff --git a/include/ns9750_sys.h b/include/ns9750_sys.h new file mode 100644 index 000000000..c563cada0 --- /dev/null +++ b/include/ns9750_sys.h @@ -0,0 +1,215 @@ +/*********************************************************************** + * + * Copyright (C) 2004 by FS Forth-Systeme GmbH. + * All rights reserved. + * + * $Id: ns9750_sys.h,v 1.1 2004/02/16 10:37:20 mpietrek Exp $ + * @Author: Markus Pietrek + * @Descr: Definitions for SYS Control Module + * @References: [1] NS9750 Hardware Reference Manual/December 2003 Chap. 4 + * + * 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 FS_NS9750_SYS_H +#define FS_NS9750_SYS_H + +#define NS9750_SYS_MODULE_BASE (0xA0900000) + +#define get_sys_reg_addr(c) \ + ((volatile unsigned int *)(NS9750_SYS_MODULE_BASE+(unsigned int) (c))) + +/* the register addresses */ + +#define NS9750_SYS_AHB_GEN (0x0000) +#define NS9750_SYS_BRC_BASE (0x0004) +#define NS9750_SYS_AHB_TIMEOUT (0x0014) +#define NS9750_SYS_AHB_ERROR1 (0x0018) +#define NS9750_SYS_AHB_ERROR2 (0x001C) +#define NS9750_SYS_AHB_MON (0x0020) +#define NS9750_SYS_TIMER_COUNT_BASE (0x0044) +#define NS9750_SYS_TIMER_READ_BASE (0x0084) +#define NS9750_SYS_INT_VEC_ADR_BASE (0x00C4) +#define NS9750_SYS_INT_CFG_BASE (0x0144) +#define NS9750_SYS_ISRADDR (0x0164) +#define NS9750_SYS_INT_STAT_ACTIVE (0x0168) +#define NS9750_SYS_INT_STAT_RAW (0x016C) +#define NS9750_SYS_TIMER_INT_STAT (0x0170) +#define NS9750_SYS_SW_WDOG_CFG (0x0174) +#define NS9750_SYS_SW_WDOG_TIMER (0x0178) +#define NS9750_SYS_CLOCK (0x017C) +#define NS9750_SYS_RESET (0x0180) +#define NS9750_SYS_MISC (0x0184) +#define NS9750_SYS_PLL (0x0188) +#define NS9750_SYS_ACT_INT_STAT (0x018C) +#define NS9750_SYS_TIMER_CTRL_BASE (0x0190) +#define NS9750_SYS_CS_DYN_BASE_BASE (0x01D0) +#define NS9750_SYS_CS_DYN_MASK_BASE (0x01D4) +#define NS9750_SYS_CS_STATIC_BASE_BASE (0x01F0) +#define NS9750_SYS_CS_STATIC_MASK_BASE (0x01F4) +#define NS9750_SYS_GEN_ID (0x0210) +#define NS9750_SYS_EXT_INT_CTRL_BASE (0x0214) + +/* the vectored register addresses */ + +#define NS9750_SYS_TIMER_COUNT(c) (NS9750_SYS_TIMER_COUNT_BASE + (c)) +#define NS9750_SYS_TIMER_READ(c) (NS9750_SYS_TIMER_READ_BASE + (c)) +#define NS9750_SYS_INT_VEC_ADR(c) (NS9750_SYS_INT_VEC_ADR_BASE + (c)) +#define NS9750_SYS_TIMER_CTRL(c) (NS9750_SYS_TIMER_CTRL_BASE + (c)) +/* CS_DYN start with 4 */ +#define NS9750_SYS_CS_DYN_BASE(c) (NS9750_SYS_CS_DYN_BASE_BASE + ((c)-4)*2) +#define NS9750_SYS_CS_DYN_MASK(c) (NS9750_SYS_CS_DYN_MASK_BASE + ((c)-4)*2) +/* CS_STATIC start with 0 */ +#define NS9750_SYS_CS_STATIC_BASE(c) (NS9750_SYS_CS_STATIC_BASE_BASE + (c)*2) +#define NS9750_SYS_CS_STATIC_MASK(c) (NS9750_SYS_CS_STATIC_MASK_BASE + (c)*2) +#define NS9750_SYS_EXT_INT_CTRL(c) (NS9750_SYS_EXT_INT_CTRL + (c)) + +/* register bit fields */ + +#define NS9750_SYS_AHB_GEN_EXMAM (0x00000001) + +/* need to be n*8bit to BRC channel */ +#define NS9750_SYS_BRC_CEB (0x00000080) +#define NS9750_SYS_BRC_BRF_MA (0x00000030) +#define NS9750_SYS_BRC_BRF_100 (0x00000000) +#define NS9750_SYS_BRC_BRF_75 (0x00000010) +#define NS9750_SYS_BRC_BRF_50 (0x00000020) +#define NS9750_SYS_BRC_BRF_25 (0x00000030) + +#define NS9750_SYS_AHB_TIMEOUT_BAT_MA (0xFFFF0000) +#define NS9750_SYS_AHB_TIMEOUT_BMT_MA (0x0000FFFF) + +#define NS9750_SYS_AHB_ERROR2_ABL (0x00040000) +#define NS9750_SYS_AHB_ERROR2_AER (0x00020000) +#define NS9750_SYS_AHB_ERROR2_ABM (0x00010000) +#define NS9750_SYS_AHB_ERROR2_ABA (0x00008000) +#define NS9750_SYS_AHB_ERROR2_HWRT (0x00004000) +#define NS9750_SYS_AHB_ERROR2_HMID_MA (0x00003C00) +#define NS9750_SYS_AHB_ERROR2_HTPC_MA (0x000003C0) +#define NS9750_SYS_AHB_ERROR2_HSZ_MA (0x00000038) +#define NS9750_SYS_AHB_ERROR2_RR_MA (0x00000007) + +#define NS9750_SYS_AHB_MON_EIC (0x00800000) +#define NS9750_SYS_AHB_MON_MBII (0x00400000) +#define NS9750_SYS_AHB_MON_MBL_MA (0x003FFFC0) +#define NS9750_SYS_AHB_MON_MBLDC (0x00000020) +#define NS9750_SYS_AHB_MON_SERDC (0x00000010) +#define NS9750_SYS_AHB_MON_BMTC_MA (0x0000000C) +#define NS9750_SYS_AHB_MON_BMTC_RECORD (0x00000000) +#define NS9750_SYS_AHB_MON_BMTC_GEN_IRQ (0x00000004) +#define NS9750_SYS_AHB_MON_BMTC_GEN_RES (0x00000008) +#define NS9750_SYS_AHB_MON_BATC_MA (0x00000003) +#define NS9750_SYS_AHB_MON_BATC_RECORD (0x00000000) +#define NS9750_SYS_AHB_MON_BATC_GEN_IRQ (0x00000001) +#define NS9750_SYS_AHB_MON_BATC_GEN_RES (0x00000002) + +/* need to be n*8bit to Int Level */ + +#define NS9750_SYS_INT_CFG_IE (0x00000080) +#define NS9750_SYS_INT_CFG_IT (0x00000020) +#define NS9750_SYS_INT_CFG_IAD_MA (0x0000001F) + +#define NS9750_SYS_TIMER_INT_STAT_MA (0x0000FFFF) + +#define NS9750_SYS_SW_WDOG_CFG_SWWE (0x00000080) +#define NS9750_SYS_SW_WDOG_CFG_SWWI (0x00000020) +#define NS9750_SYS_SW_WDOG_CFG_SWWIC (0x00000010) +#define NS9750_SYS_SW_WDOG_CFG_SWTCS_MA (0x00000007) +#define NS9750_SYS_SW_WDOG_CFG_SWTCS_2 (0x00000000) +#define NS9750_SYS_SW_WDOG_CFG_SWTCS_4 (0x00000001) +#define NS9750_SYS_SW_WDOG_CFG_SWTCS_8 (0x00000002) +#define NS9750_SYS_SW_WDOG_CFG_SWTCS_16 (0x00000003) +#define NS9750_SYS_SW_WDOG_CFG_SWTCS_32 (0x00000004) +#define NS9750_SYS_SW_WDOG_CFG_SWTCS_64 (0x00000005) + +#define NS9750_SYS_CLOCK_LPCS_MA (0x00000380) +#define NS9750_SYS_CLOCK_LPCS_1 (0x00000000) +#define NS9750_SYS_CLOCK_LPCS_2 (0x00000080) +#define NS9750_SYS_CLOCK_LPCS_4 (0x00000100) +#define NS9750_SYS_CLOCK_LPCS_8 (0x00000180) +#define NS9750_SYS_CLOCK_LPCS_EXT (0x00000200) +#define NS9750_SYS_CLOCK_BBC (0x00000040) +#define NS9750_SYS_CLOCK_LCC (0x00000020) +#define NS9750_SYS_CLOCK_MCC (0x00000010) +#define NS9750_SYS_CLOCK_PARBC (0x00000008) +#define NS9750_SYS_CLOCK_PC (0x00000004) +#define NS9750_SYS_CLOCK_MACC (0x00000001) + +#define NS9750_SYS_RESET_SR (0x80000000) +#define NS9750_SYS_RESET_I2CW (0x00100000) +#define NS9750_SYS_RESET_CSE (0x00080000) +#define NS9750_SYS_RESET_SMWE (0x00040000) +#define NS9750_SYS_RESET_EWE (0x00020000) +#define NS9750_SYS_RESET_PI3WE (0x00010000) +#define NS9750_SYS_RESET_BBT (0x00000040) +#define NS9750_SYS_RESET_LCDC (0x00000020) +#define NS9750_SYS_RESET_MEMC (0x00000010) +#define NS9750_SYS_RESET_PCIAR (0x00000008) +#define NS9750_SYS_RESET_PCIM (0x00000004) +#define NS9750_SYS_RESET_MACM (0x00000001) + +#define NS9750_SYS_MISC_REV_MA (0xFF000000) +#define NS9750_SYS_MISC_PCIA (0x00002000) +#define NS9750_SYS_MISC_VDIS (0x00001000) +#define NS9750_SYS_MISC_BMM (0x00000800) +#define NS9750_SYS_MISC_CS1DB (0x00000400) +#define NS9750_SYS_MISC_CS1DW_MA (0x00000300) +#define NS9750_SYS_MISC_MCCM (0x00000080) +#define NS9750_SYS_MISC_PMSS (0x00000040) +#define NS9750_SYS_MISC_CS1P (0x00000020) +#define NS9750_SYS_MISC_ENDM (0x00000008) +#define NS9750_SYS_MISC_MBAR (0x00000004) +#define NS9750_SYS_MISC_IRAM0 (0x00000001) + +#define NS9750_SYS_PLL_PLLBS (0x02000000) +#define NS9750_SYS_PLL_PLLFS_MA (0x01800000) +#define NS9750_SYS_PLL_PLLIS_MA (0x00600000) +#define NS9750_SYS_PLL_PLLND_MA (0x001F0000) +#define NS9750_SYS_PLL_PLLSW (0x00008000) +#define NS9750_SYS_PLL_PLLBSSW (0x00000200) +#define NS9750_SYS_PLL_FSEL_MA (0x00000180) +#define NS9750_SYS_PLL_CPCC_MA (0x00000060) +#define NS9750_SYS_PLL_NDSW_MA (0x0000001F) + +#define NS9750_SYS_ACT_INT_STAT_MA (0x0000FFFF) + +#define NS9750_SYS_TIMER_CTRL_TEN (0x00008000) +#define NS9750_SYS_TIMER_CTRL_INTC (0x00000200) +#define NS9750_SYS_TIMER_CTRL_TLCS_MA (0x000001C0) +#define NS9750_SYS_TIMER_CTRL_TLCS_1 (0x00000000) +#define NS9750_SYS_TIMER_CTRL_TLCS_2 (0x00000040) +#define NS9750_SYS_TIMER_CTRL_TLCS_4 (0x00000080) +#define NS9750_SYS_TIMER_CTRL_TLCS_8 (0x000000C0) +#define NS9750_SYS_TIMER_CTRL_TLCS_16 (0x00000100) +#define NS9750_SYS_TIMER_CTRL_TLCS_32 (0x00000140) +#define NS9750_SYS_TIMER_CTRL_TLCS_64 (0x00000180) +#define NS9750_SYS_TIMER_CTRL_TLCS_EXT (0x000001C0) +#define NS9750_SYS_TIMER_CTRL_TM_MA (0x00000030) +#define NS9750_SYS_TIMER_CTRL_TM_INT (0x00000000) +#define NS9750_SYS_TIMER_CTRL_TM_LOW (0x00000010) +#define NS9750_SYS_TIMER_CTRL_TM_HIGH (0x00000020) +#define NS9750_SYS_TIMER_CTRL_INTS (0x00000008) +#define NS9750_SYS_TIMER_CTRL_UDS (0x00000004) +#define NS9750_SYS_TIMER_CTRL_TSZ (0x00000002) +#define NS9750_SYS_TIMER_CTRL_REN (0x00000001) + +#define NS9750_SYS_EXT_INT_CTRL_STS (0x00000008) +#define NS9750_SYS_EXT_INT_CTRL_CLR (0x00000004) +#define NS9750_SYS_EXT_INT_CTRL_PLTY (0x00000002) +#define NS9750_SYS_EXT_INT_CTRL_LVEDG (0x00000001) + +#endif /* FS_NS9750_SYS_H */