summaryrefslogtreecommitdiffstats
path: root/package/uboot-ifxmips/files/cpu/mips
diff options
context:
space:
mode:
authornbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>2008-06-28 19:53:41 +0000
committernbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>2008-06-28 19:53:41 +0000
commit240bf1625edcc439b62aea43a0983f8207b541b1 (patch)
treea2b20d7ed8890acb2de9a5436db408b52a2f1aac /package/uboot-ifxmips/files/cpu/mips
parente9e6238a631e0015f4e35688291479d075637d7e (diff)
move ifxmips uboot to package/
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@11601 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'package/uboot-ifxmips/files/cpu/mips')
-rw-r--r--package/uboot-ifxmips/files/cpu/mips/danube/Makefile49
-rw-r--r--package/uboot-ifxmips/files/cpu/mips/danube/asc_serial.c371
-rw-r--r--package/uboot-ifxmips/files/cpu/mips/danube/asc_serial.h177
-rw-r--r--package/uboot-ifxmips/files/cpu/mips/danube/au1x00_eth.c311
-rw-r--r--package/uboot-ifxmips/files/cpu/mips/danube/au1x00_serial.c135
-rw-r--r--package/uboot-ifxmips/files/cpu/mips/danube/au1x00_usb_ohci.c1727
-rw-r--r--package/uboot-ifxmips/files/cpu/mips/danube/au1x00_usb_ohci.h416
-rw-r--r--package/uboot-ifxmips/files/cpu/mips/danube/cache.S278
-rw-r--r--package/uboot-ifxmips/files/cpu/mips/danube/config.mk53
-rw-r--r--package/uboot-ifxmips/files/cpu/mips/danube/cpu.c61
-rw-r--r--package/uboot-ifxmips/files/cpu/mips/danube/ifx_asc.c257
-rw-r--r--package/uboot-ifxmips/files/cpu/mips/danube/ifx_cache.S60
-rw-r--r--package/uboot-ifxmips/files/cpu/mips/danube/ifx_cgu.c1086
-rw-r--r--package/uboot-ifxmips/files/cpu/mips/danube/ifx_cgu.h91
-rw-r--r--package/uboot-ifxmips/files/cpu/mips/danube/ifx_clock.c91
-rw-r--r--package/uboot-ifxmips/files/cpu/mips/danube/ifx_cpu.c5
-rw-r--r--package/uboot-ifxmips/files/cpu/mips/danube/ifx_start.S51
-rw-r--r--package/uboot-ifxmips/files/cpu/mips/danube/incaip_clock.c120
-rw-r--r--package/uboot-ifxmips/files/cpu/mips/danube/incaip_wdt.S75
-rw-r--r--package/uboot-ifxmips/files/cpu/mips/danube/interrupts.c33
-rw-r--r--package/uboot-ifxmips/files/cpu/mips/danube/start.S442
-rw-r--r--package/uboot-ifxmips/files/cpu/mips/danube/start_bootstrap.S428
22 files changed, 6317 insertions, 0 deletions
diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/Makefile b/package/uboot-ifxmips/files/cpu/mips/danube/Makefile
new file mode 100644
index 000000000..da329b378
--- /dev/null
+++ b/package/uboot-ifxmips/files/cpu/mips/danube/Makefile
@@ -0,0 +1,49 @@
+#
+# (C) Copyright 2003-2006
+# 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 = $(obj)lib$(CPU).a
+
+START = start.o
+COBJS = asc_serial.o au1x00_serial.o au1x00_eth.o au1x00_usb_ohci.o \
+ cpu.o interrupts.o incaip_clock.o ifx_asc.o ifx_clock.o
+SOBJS = incaip_wdt.o cache.o
+
+SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
+START := $(addprefix $(obj),$(START))
+
+all: $(obj).depend $(START) $(LIB)
+
+$(LIB): $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/asc_serial.c b/package/uboot-ifxmips/files/cpu/mips/danube/asc_serial.c
new file mode 100644
index 000000000..d95ec3fd2
--- /dev/null
+++ b/package/uboot-ifxmips/files/cpu/mips/danube/asc_serial.c
@@ -0,0 +1,371 @@
+/*
+ * (INCA) ASC UART support
+ */
+
+#include <config.h>
+
+#if defined(CONFIG_PURPLE) || defined(CONFIG_INCA_IP)
+
+#ifdef CONFIG_PURPLE
+#define serial_init asc_serial_init
+#define serial_putc asc_serial_putc
+#define serial_puts asc_serial_puts
+#define serial_getc asc_serial_getc
+#define serial_tstc asc_serial_tstc
+#define serial_setbrg asc_serial_setbrg
+#endif
+
+#include <common.h>
+#include <asm/inca-ip.h>
+#include "asc_serial.h"
+
+#ifdef CONFIG_PURPLE
+
+#undef ASC_FIFO_PRESENT
+#define TOUT_LOOP 100000
+
+/* Set base address for second FPI interrupt control register bank */
+#define SFPI_INTCON_BASEADDR 0xBF0F0000
+
+/* Register offset from base address */
+#define FBS_ISR 0x00000000 /* Interrupt status register */
+#define FBS_IMR 0x00000008 /* Interrupt mask register */
+#define FBS_IDIS 0x00000010 /* Interrupt disable register */
+
+/* Interrupt status register bits */
+#define FBS_ISR_AT 0x00000040 /* ASC transmit interrupt */
+#define FBS_ISR_AR 0x00000020 /* ASC receive interrupt */
+#define FBS_ISR_AE 0x00000010 /* ASC error interrupt */
+#define FBS_ISR_AB 0x00000008 /* ASC transmit buffer interrupt */
+#define FBS_ISR_AS 0x00000004 /* ASC start of autobaud detection interrupt */
+#define FBS_ISR_AF 0x00000002 /* ASC end of autobaud detection interrupt */
+
+#else
+
+#define ASC_FIFO_PRESENT
+
+#endif
+
+
+#define SET_BIT(reg, mask) reg |= (mask)
+#define CLEAR_BIT(reg, mask) reg &= (~mask)
+#define CLEAR_BITS(reg, mask) CLEAR_BIT(reg, mask)
+#define SET_BITS(reg, mask) SET_BIT(reg, mask)
+#define SET_BITFIELD(reg, mask, off, val) {reg &= (~mask); reg |= (val << off);}
+
+extern uint incaip_get_fpiclk(void);
+
+static int serial_setopt (void);
+
+/* pointer to ASC register base address */
+static volatile incaAsc_t *pAsc = (incaAsc_t *)INCA_IP_ASC;
+
+/******************************************************************************
+*
+* serial_init - initialize a INCAASC channel
+*
+* This routine initializes the number of data bits, parity
+* and set the selected baud rate. Interrupts are disabled.
+* Set the modem control signals if the option is selected.
+*
+* RETURNS: N/A
+*/
+
+int serial_init (void)
+{
+#ifdef CONFIG_INCA_IP
+ /* we have to set PMU.EN13 bit to enable an ASC device*/
+ INCAASC_PMU_ENABLE(13);
+#endif
+
+ /* and we have to set CLC register*/
+ CLEAR_BIT(pAsc->asc_clc, ASCCLC_DISS);
+ SET_BITFIELD(pAsc->asc_clc, ASCCLC_RMCMASK, ASCCLC_RMCOFFSET, 0x0001);
+
+ /* initialy we are in async mode */
+ pAsc->asc_con = ASCCON_M_8ASYNC;
+
+ /* select input port */
+ pAsc->asc_pisel = (CONSOLE_TTY & 0x1);
+
+#ifdef ASC_FIFO_PRESENT
+ /* TXFIFO's filling level */
+ SET_BITFIELD(pAsc->asc_txfcon, ASCTXFCON_TXFITLMASK,
+ ASCTXFCON_TXFITLOFF, INCAASC_TXFIFO_FL);
+ /* enable TXFIFO */
+ SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXFEN);
+
+ /* RXFIFO's filling level */
+ SET_BITFIELD(pAsc->asc_txfcon, ASCRXFCON_RXFITLMASK,
+ ASCRXFCON_RXFITLOFF, INCAASC_RXFIFO_FL);
+ /* enable RXFIFO */
+ SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXFEN);
+#endif
+
+ /* enable error signals */
+ SET_BIT(pAsc->asc_con, ASCCON_FEN);
+ SET_BIT(pAsc->asc_con, ASCCON_OEN);
+
+#ifdef CONFIG_INCA_IP
+ /* acknowledge ASC interrupts */
+ ASC_INTERRUPTS_CLEAR(INCAASC_IRQ_LINE_ALL);
+
+ /* disable ASC interrupts */
+ ASC_INTERRUPTS_DISABLE(INCAASC_IRQ_LINE_ALL);
+#endif
+
+#ifdef ASC_FIFO_PRESENT
+ /* set FIFOs into the transparent mode */
+ SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXTMEN);
+ SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXTMEN);
+#endif
+
+ /* set baud rate */
+ serial_setbrg();
+
+ /* set the options */
+ serial_setopt();
+
+ return 0;
+}
+
+void serial_setbrg (void)
+{
+ ulong uiReloadValue, fdv;
+ ulong f_ASC;
+
+#ifdef CONFIG_INCA_IP
+ f_ASC = incaip_get_fpiclk();
+#else
+ f_ASC = ASC_CLOCK_RATE;
+#endif
+
+#ifndef INCAASC_USE_FDV
+ fdv = 2;
+ uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1;
+#else
+ fdv = INCAASC_FDV_HIGH_BAUDRATE;
+ uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1;
+#endif /* INCAASC_USE_FDV */
+
+ if ( (uiReloadValue < 0) || (uiReloadValue > 8191) )
+ {
+#ifndef INCAASC_USE_FDV
+ fdv = 3;
+ uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1;
+#else
+ fdv = INCAASC_FDV_LOW_BAUDRATE;
+ uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1;
+#endif /* INCAASC_USE_FDV */
+
+ if ( (uiReloadValue < 0) || (uiReloadValue > 8191) )
+ {
+ return; /* can't impossibly generate that baud rate */
+ }
+ }
+
+ /* Disable Baud Rate Generator; BG should only be written when R=0 */
+ CLEAR_BIT(pAsc->asc_con, ASCCON_R);
+
+#ifndef INCAASC_USE_FDV
+ /*
+ * Disable Fractional Divider (FDE)
+ * Divide clock by reload-value + constant (BRS)
+ */
+ /* FDE = 0 */
+ CLEAR_BIT(pAsc->asc_con, ASCCON_FDE);
+
+ if ( fdv == 2 )
+ CLEAR_BIT(pAsc->asc_con, ASCCON_BRS); /* BRS = 0 */
+ else
+ SET_BIT(pAsc->asc_con, ASCCON_BRS); /* BRS = 1 */
+
+#else /* INCAASC_USE_FDV */
+
+ /* Enable Fractional Divider */
+ SET_BIT(pAsc->asc_con, ASCCON_FDE); /* FDE = 1 */
+
+ /* Set fractional divider value */
+ pAsc->asc_fdv = fdv & ASCFDV_VALUE_MASK;
+
+#endif /* INCAASC_USE_FDV */
+
+ /* Set reload value in BG */
+ pAsc->asc_bg = uiReloadValue;
+
+ /* Enable Baud Rate Generator */
+ SET_BIT(pAsc->asc_con, ASCCON_R); /* R = 1 */
+}
+
+/*******************************************************************************
+*
+* serial_setopt - set the serial options
+*
+* Set the channel operating mode to that specified. Following options
+* are supported: CREAD, CSIZE, PARENB, and PARODD.
+*
+* Note, this routine disables the transmitter. The calling routine
+* may have to re-enable it.
+*
+* RETURNS:
+* Returns 0 to indicate success, otherwise -1 is returned
+*/
+
+static int serial_setopt (void)
+{
+ ulong con;
+
+ switch ( ASC_OPTIONS & ASCOPT_CSIZE )
+ {
+ /* 7-bit-data */
+ case ASCOPT_CS7:
+ con = ASCCON_M_7ASYNCPAR; /* 7-bit-data and parity bit */
+ break;
+
+ /* 8-bit-data */
+ case ASCOPT_CS8:
+ if ( ASC_OPTIONS & ASCOPT_PARENB )
+ con = ASCCON_M_8ASYNCPAR; /* 8-bit-data and parity bit */
+ else
+ con = ASCCON_M_8ASYNC; /* 8-bit-data no parity */
+ break;
+
+ /*
+ * only 7 and 8-bit frames are supported
+ * if we don't use IOCTL extensions
+ */
+ default:
+ return -1;
+ }
+
+ if ( ASC_OPTIONS & ASCOPT_STOPB )
+ SET_BIT(con, ASCCON_STP); /* 2 stop bits */
+ else
+ CLEAR_BIT(con, ASCCON_STP); /* 1 stop bit */
+
+ if ( ASC_OPTIONS & ASCOPT_PARENB )
+ SET_BIT(con, ASCCON_PEN); /* enable parity checking */
+ else
+ CLEAR_BIT(con, ASCCON_PEN); /* disable parity checking */
+
+ if ( ASC_OPTIONS & ASCOPT_PARODD )
+ SET_BIT(con, ASCCON_ODD); /* odd parity */
+ else
+ CLEAR_BIT(con, ASCCON_ODD); /* even parity */
+
+ if ( ASC_OPTIONS & ASCOPT_CREAD )
+ SET_BIT(pAsc->asc_whbcon, ASCWHBCON_SETREN); /* Receiver enable */
+
+ pAsc->asc_con |= con;
+
+ return 0;
+}
+
+void serial_putc (const char c)
+{
+#ifdef ASC_FIFO_PRESENT
+ uint txFl = 0;
+#else
+ uint timeout = 0;
+#endif
+
+ if (c == '\n') serial_putc ('\r');
+
+#ifdef ASC_FIFO_PRESENT
+ /* check do we have a free space in the TX FIFO */
+ /* get current filling level */
+ do
+ {
+ txFl = ( pAsc->asc_fstat & ASCFSTAT_TXFFLMASK ) >> ASCFSTAT_TXFFLOFF;
+ }
+ while ( txFl == INCAASC_TXFIFO_FULL );
+#else
+
+ while(!(*(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) &
+ FBS_ISR_AB))
+ {
+ if (timeout++ > TOUT_LOOP)
+ {
+ break;
+ }
+ }
+#endif
+
+ pAsc->asc_tbuf = c; /* write char to Transmit Buffer Register */
+
+#ifndef ASC_FIFO_PRESENT
+ *(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) = FBS_ISR_AB |
+ FBS_ISR_AT;
+#endif
+
+ /* check for errors */
+ if ( pAsc->asc_con & ASCCON_OE )
+ {
+ SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE);
+ return;
+ }
+}
+
+void serial_puts (const char *s)
+{
+ while (*s)
+ {
+ serial_putc (*s++);
+ }
+}
+
+int serial_getc (void)
+{
+ ulong symbol_mask;
+ char c;
+
+ while (!serial_tstc());
+
+ symbol_mask =
+ ((ASC_OPTIONS & ASCOPT_CSIZE) == ASCOPT_CS7) ? (0x7f) : (0xff);
+
+ c = (char)(pAsc->asc_rbuf & symbol_mask);
+
+#ifndef ASC_FIFO_PRESENT
+ *(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) = FBS_ISR_AR;
+#endif
+
+ return c;
+}
+
+int serial_tstc (void)
+{
+ int res = 1;
+
+#ifdef ASC_FIFO_PRESENT
+ if ( (pAsc->asc_fstat & ASCFSTAT_RXFFLMASK) == 0 )
+ {
+ res = 0;
+ }
+#else
+ if (!(*(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) &
+ FBS_ISR_AR))
+
+ {
+ res = 0;
+ }
+#endif
+ else if ( pAsc->asc_con & ASCCON_FE )
+ {
+ SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRFE);
+ res = 0;
+ }
+ else if ( pAsc->asc_con & ASCCON_PE )
+ {
+ SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRPE);
+ res = 0;
+ }
+ else if ( pAsc->asc_con & ASCCON_OE )
+ {
+ SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE);
+ res = 0;
+ }
+
+ return res;
+}
+#endif /* CONFIG_PURPLE || CONFIG_INCA_IP */
diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/asc_serial.h b/package/uboot-ifxmips/files/cpu/mips/danube/asc_serial.h
new file mode 100644
index 000000000..7ffdcfaf8
--- /dev/null
+++ b/package/uboot-ifxmips/files/cpu/mips/danube/asc_serial.h
@@ -0,0 +1,177 @@
+/* incaAscSio.h - (INCA) ASC UART tty driver header */
+
+#ifndef __INCincaAscSioh
+#define __INCincaAscSioh
+
+#include <asm/inca-ip.h>
+
+/* channel operating modes */
+#define ASCOPT_CSIZE 0x00000003
+#define ASCOPT_CS7 0x00000001
+#define ASCOPT_CS8 0x00000002
+#define ASCOPT_PARENB 0x00000004
+#define ASCOPT_STOPB 0x00000008
+#define ASCOPT_PARODD 0x00000010
+#define ASCOPT_CREAD 0x00000020
+
+#define ASC_OPTIONS (ASCOPT_CREAD | ASCOPT_CS8)
+
+/* ASC input select (0 or 1) */
+#define CONSOLE_TTY 0
+
+/* use fractional divider for baudrate settings */
+#define INCAASC_USE_FDV
+
+#ifdef INCAASC_USE_FDV
+ #define INCAASC_FDV_LOW_BAUDRATE 71
+ #define INCAASC_FDV_HIGH_BAUDRATE 453
+#endif /*INCAASC_USE_FDV*/
+
+
+#define INCAASC_TXFIFO_FL 1
+#define INCAASC_RXFIFO_FL 1
+#define INCAASC_TXFIFO_FULL 16
+
+/* interrupt lines masks for the ASC device interrupts*/
+/* change these macroses if it's necessary */
+#define INCAASC_IRQ_LINE_ALL 0x000F0000 /* all IRQs */
+
+#define INCAASC_IRQ_LINE_TIR 0x00010000 /* TIR - Tx */
+#define INCAASC_IRQ_LINE_RIR 0x00020000 /* RIR - Rx */
+#define INCAASC_IRQ_LINE_EIR 0x00040000 /* EIR - Err */
+#define INCAASC_IRQ_LINE_TBIR 0x00080000 /* TBIR - Tx Buf*/
+
+/* interrupt controller access macros */
+#define ASC_INTERRUPTS_ENABLE(X) \
+ *((volatile unsigned int*) INCA_IP_ICU_IM2_IER) |= X;
+#define ASC_INTERRUPTS_DISABLE(X) \
+ *((volatile unsigned int*) INCA_IP_ICU_IM2_IER) &= ~X;
+#define ASC_INTERRUPTS_CLEAR(X) \
+ *((volatile unsigned int*) INCA_IP_ICU_IM2_ISR) = X;
+
+/* CLC register's bits and bitfields */
+#define ASCCLC_DISR 0x00000001
+#define ASCCLC_DISS 0x00000002
+#define ASCCLC_RMCMASK 0x0000FF00
+#define ASCCLC_RMCOFFSET 8
+
+/* CON register's bits and bitfields */
+#define ASCCON_MODEMASK 0x0007
+ #define ASCCON_M_8SYNC 0x0
+ #define ASCCON_M_8ASYNC 0x1
+ #define ASCCON_M_8IRDAASYNC 0x2
+ #define ASCCON_M_7ASYNCPAR 0x3
+ #define ASCCON_M_9ASYNC 0x4
+ #define ASCCON_M_8WAKEUPASYNC 0x5
+ #define ASCCON_M_8ASYNCPAR 0x7
+#define ASCCON_STP 0x0008
+#define ASCCON_REN 0x0010
+#define ASCCON_PEN 0x0020
+#define ASCCON_FEN 0x0040
+#define ASCCON_OEN 0x0080
+#define ASCCON_PE 0x0100
+#define ASCCON_FE 0x0200
+#define ASCCON_OE 0x0400
+#define ASCCON_FDE 0x0800
+#define ASCCON_ODD 0x1000
+#define ASCCON_BRS 0x2000
+#define ASCCON_LB 0x4000
+#define ASCCON_R 0x8000
+
+/* WHBCON register's bits and bitfields */
+#define ASCWHBCON_CLRREN 0x0010
+#define ASCWHBCON_SETREN 0x0020
+#define ASCWHBCON_CLRPE 0x0100
+#define ASCWHBCON_CLRFE 0x0200
+#define ASCWHBCON_CLROE 0x0400
+#define ASCWHBCON_SETPE 0x0800
+#define ASCWHBCON_SETFE 0x1000
+#define ASCWHBCON_SETOE 0x2000
+
+/* ABCON register's bits and bitfields */
+#define ASCABCON_ABEN 0x0001
+#define ASCABCON_AUREN 0x0002
+#define ASCABCON_ABSTEN 0x0004
+#define ASCABCON_ABDETEN 0x0008
+#define ASCABCON_FCDETEN 0x0010
+#define ASCABCON_EMMASK 0x0300
+ #define ASCABCON_EMOFF 8
+ #define ASCABCON_EM_DISAB 0x0
+ #define ASCABCON_EM_DURAB 0x1
+ #define ASCABCON_EM_ALWAYS 0x2
+#define ASCABCON_TXINV 0x0400
+#define ASCABCON_RXINV 0x0800
+
+/* FDV register mask, offset and bitfields*/
+#define ASCFDV_VALUE_MASK 0x000001FF
+
+/* WHBABCON register's bits and bitfields */
+#define ASCWHBABCON_SETABEN 0x0001
+#define ASCWHBABCON_CLRABEN 0x0002
+
+/* ABSTAT register's bits and bitfields */
+#define ASCABSTAT_FCSDET 0x0001
+#define ASCABSTAT_FCCDET 0x0002
+#define ASCABSTAT_SCSDET 0x0004
+#define ASCABSTAT_SCCDET 0x0008
+#define ASCABSTAT_DETWAIT 0x0010
+
+/* WHBABSTAT register's bits and bitfields */
+#define ASCWHBABSTAT_CLRFCSDET 0x0001
+#define ASCWHBABSTAT_SETFCSDET 0x0002
+#define ASCWHBABSTAT_CLRFCCDET 0x0004
+#define ASCWHBABSTAT_SETFCCDET 0x0008
+#define ASCWHBABSTAT_CLRSCSDET 0x0010
+#define ASCWHBABSTAT_SETSCSDET 0x0020
+#define ASCWHBABSTAT_SETSCCDET 0x0040
+#define ASCWHBABSTAT_CLRSCCDET 0x0080
+#define ASCWHBABSTAT_CLRDETWAIT 0x0100
+#define ASCWHBABSTAT_SETDETWAIT 0x0200
+
+/* TXFCON register's bits and bitfields */
+#define ASCTXFCON_TXFEN 0x0001
+#define ASCTXFCON_TXFFLU 0x0002
+#define ASCTXFCON_TXTMEN 0x0004
+#define ASCTXFCON_TXFITLMASK 0x3F00
+#define ASCTXFCON_TXFITLOFF 8
+
+/* RXFCON register's bits and bitfields */
+#define ASCRXFCON_RXFEN 0x0001
+#define ASCRXFCON_RXFFLU 0x0002
+#define ASCRXFCON_RXTMEN 0x0004
+#define ASCRXFCON_RXFITLMASK 0x3F00
+#define ASCRXFCON_RXFITLOFF 8
+
+/* FSTAT register's bits and bitfields */
+#define ASCFSTAT_RXFFLMASK 0x003F
+#define ASCFSTAT_TXFFLMASK 0x3F00
+#define ASCFSTAT_TXFFLOFF 8
+
+#define INCAASC_PMU_ENABLE(BIT) *((volatile ulong*)0xBF102000) |= (0x1 << BIT);
+
+typedef struct /* incaAsc_t */
+{
+ volatile unsigned long asc_clc; /*0x0000*/
+ volatile unsigned long asc_pisel; /*0x0004*/
+ volatile unsigned long asc_rsvd1[2]; /* for mapping */ /*0x0008*/
+ volatile unsigned long asc_con; /*0x0010*/
+ volatile unsigned long asc_bg; /*0x0014*/
+ volatile unsigned long asc_fdv; /*0x0018*/
+ volatile unsigned long asc_pmw; /* not used */ /*0x001C*/
+ volatile unsigned long asc_tbuf; /*0x0020*/
+ volatile unsigned long asc_rbuf; /*0x0024*/
+ volatile unsigned long asc_rsvd2[2]; /* for mapping */ /*0x0028*/
+ volatile unsigned long asc_abcon; /*0x0030*/
+ volatile unsigned long asc_abstat; /* not used */ /*0x0034*/
+ volatile unsigned long asc_rsvd3[2]; /* for mapping */ /*0x0038*/
+ volatile unsigned long asc_rxfcon; /*0x0040*/
+ volatile unsigned long asc_txfcon; /*0x0044*/
+ volatile unsigned long asc_fstat; /*0x0048*/
+ volatile unsigned long asc_rsvd4; /* for mapping */ /*0x004C*/
+ volatile unsigned long asc_whbcon; /*0x0050*/
+ volatile unsigned long asc_whbabcon; /*0x0054*/
+ volatile unsigned long asc_whbabstat; /* not used */ /*0x0058*/
+
+} incaAsc_t;
+
+#endif /* __INCincaAscSioh */
diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/au1x00_eth.c b/package/uboot-ifxmips/files/cpu/mips/danube/au1x00_eth.c
new file mode 100644
index 000000000..078e8328b
--- /dev/null
+++ b/package/uboot-ifxmips/files/cpu/mips/danube/au1x00_eth.c
@@ -0,0 +1,311 @@
+/* Only eth0 supported for now
+ *
+ * (C) Copyright 2003
+ * Thomas.Lange@corelatus.se
+ *
+ * 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 <config.h>
+
+#ifdef CONFIG_AU1X00
+
+#if defined(CFG_DISCOVER_PHY)
+#error "PHY not supported yet"
+/* We just assume that we are running 100FD for now */
+/* We all use switches, right? ;-) */
+#endif
+
+/* I assume ethernet behaves like au1000 */
+
+#ifdef CONFIG_AU1000
+/* Base address differ between cpu:s */
+#define ETH0_BASE AU1000_ETH0_BASE
+#define MAC0_ENABLE AU1000_MAC0_ENABLE
+#else
+#ifdef CONFIG_AU1100
+#define ETH0_BASE AU1100_ETH0_BASE
+#define MAC0_ENABLE AU1100_MAC0_ENABLE
+#else
+#ifdef CONFIG_AU1500
+#define ETH0_BASE AU1500_ETH0_BASE
+#define MAC0_ENABLE AU1500_MAC0_ENABLE
+#else
+#ifdef CONFIG_AU1550
+#define ETH0_BASE AU1550_ETH0_BASE
+#define MAC0_ENABLE AU1550_MAC0_ENABLE
+#else
+#error "No valid cpu set"
+#endif
+#endif
+#endif
+#endif
+
+#include <common.h>
+#include <malloc.h>
+#include <net.h>
+#include <command.h>
+#include <asm/io.h>
+#include <asm/au1x00.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_MII)
+#include <miiphy.h>
+#endif
+
+/* Ethernet Transmit and Receive Buffers */
+#define DBUF_LENGTH 1520
+#define PKT_MAXBUF_SIZE 1518
+
+static char txbuf[DBUF_LENGTH];
+
+static int next_tx;
+static int next_rx;
+
+/* 4 rx and 4 tx fifos */
+#define NO_OF_FIFOS 4
+
+typedef struct{
+ u32 status;
+ u32 addr;
+ u32 len; /* Only used for tx */
+ u32 not_used;
+} mac_fifo_t;
+
+mac_fifo_t mac_fifo[NO_OF_FIFOS];
+
+#define MAX_WAIT 1000
+
+static int au1x00_send(struct eth_device* dev, volatile void *packet, int length){
+ volatile mac_fifo_t *fifo_tx =
+ (volatile mac_fifo_t*)(MAC0_TX_DMA_ADDR+MAC_TX_BUFF0_STATUS);
+ int i;
+ int res;
+
+ /* tx fifo should always be idle */
+ fifo_tx[next_tx].len = length;
+ fifo_tx[next_tx].addr = (virt_to_phys(packet))|TX_DMA_ENABLE;
+ au_sync();
+
+ udelay(1);
+ i=0;
+ while(!(fifo_tx[next_tx].addr&TX_T_DONE)){
+ if(i>MAX_WAIT){
+ printf("TX timeout\n");
+ break;
+ }
+ udelay(1);
+ i++;
+ }
+
+ /* Clear done bit */
+ fifo_tx[next_tx].addr = 0;
+ fifo_tx[next_tx].len = 0;
+ au_sync();
+
+ res = fifo_tx[next_tx].status;
+
+ next_tx++;
+ if(next_tx>=NO_OF_FIFOS){
+ next_tx=0;
+ }
+ return(res);
+}
+
+static int au1x00_recv(struct eth_device* dev){
+ volatile mac_fifo_t *fifo_rx =
+ (volatile mac_fifo_t*)(MAC0_RX_DMA_ADDR+MAC_RX_BUFF0_STATUS);
+
+ int length;
+ u32 status;
+
+ for(;;){
+ if(!(fifo_rx[next_rx].addr&RX_T_DONE)){
+ /* Nothing has been received */
+ return(-1);
+ }
+
+ status = fifo_rx[next_rx].status;
+
+ length = status&0x3FFF;
+
+ if(status&RX_ERROR){
+ printf("Rx error 0x%x\n", status);
+ }
+ else{
+ /* Pass the packet up to the protocol layers. */
+ NetReceive(NetRxPackets[next_rx], length - 4);
+ }
+
+ fifo_rx[next_rx].addr = (virt_to_phys(NetRxPackets[next_rx]))|RX_DMA_ENABLE;
+
+ next_rx++;
+ if(next_rx>=NO_OF_FIFOS){
+ next_rx=0;
+ }
+ } /* for */
+
+ return(0); /* Does anyone use this? */
+}
+
+static int au1x00_init(struct eth_device* dev, bd_t * bd){
+
+ volatile u32 *macen = (volatile u32*)MAC0_ENABLE;
+ volatile u32 *mac_ctrl = (volatile u32*)(ETH0_BASE+MAC_CONTROL);
+ volatile u32 *mac_addr_high = (volatile u32*)(ETH0_BASE+MAC_ADDRESS_HIGH);
+ volatile u32 *mac_addr_low = (volatile u32*)(ETH0_BASE+MAC_ADDRESS_LOW);
+ volatile u32 *mac_mcast_high = (volatile u32*)(ETH0_BASE+MAC_MCAST_HIGH);
+ volatile u32 *mac_mcast_low = (volatile u32*)(ETH0_BASE+MAC_MCAST_LOW);
+ volatile mac_fifo_t *fifo_tx =
+ (volatile mac_fifo_t*)(MAC0_TX_DMA_ADDR+MAC_TX_BUFF0_STATUS);
+ volatile mac_fifo_t *fifo_rx =
+ (volatile mac_fifo_t*)(MAC0_RX_DMA_ADDR+MAC_RX_BUFF0_STATUS);
+ int i;
+
+ next_tx = TX_GET_DMA_BUFFER(fifo_tx[0].addr);
+ next_rx = RX_GET_DMA_BUFFER(fifo_rx[0].addr);
+
+ /* We have to enable clocks before releasing reset */
+ *macen = MAC_EN_CLOCK_ENABLE;
+ udelay(10);
+
+ /* Enable MAC0 */
+ /* We have to release reset before accessing registers */
+ *macen = MAC_EN_CLOCK_ENABLE|MAC_EN_RESET0|
+ MAC_EN_RESET1|MAC_EN_RESET2;
+ udelay(10);
+
+ for(i=0;i<NO_OF_FIFOS;i++){
+ fifo_tx[i].len = 0;
+ fifo_tx[i].addr = virt_to_phys(&txbuf[0]);
+ fifo_rx[i].addr = (virt_to_phys(NetRxPackets[i]))|RX_DMA_ENABLE;
+ }
+
+ /* Put mac addr in little endian */
+#define ea eth_get_dev()->enetaddr
+ *mac_addr_high = (ea[5] << 8) | (ea[4] ) ;
+ *mac_addr_low = (ea[3] << 24) | (ea[2] << 16) |
+ (ea[1] << 8) | (ea[0] ) ;
+#undef ea
+ *mac_mcast_low = 0;
+ *mac_mcast_high = 0;
+
+ /* Make sure the MAC buffer is in the correct endian mode */
+#ifdef __LITTLE_ENDIAN
+ *mac_ctrl = MAC_FULL_DUPLEX;
+ udelay(1);
+ *mac_ctrl = MAC_FULL_DUPLEX|MAC_RX_ENABLE|MAC_TX_ENABLE;
+#else
+ *mac_ctrl = MAC_BIG_ENDIAN|MAC_FULL_DUPLEX;
+ udelay(1);
+ *mac_ctrl = MAC_BIG_ENDIAN|MAC_FULL_DUPLEX|MAC_RX_ENABLE|MAC_TX_ENABLE;
+#endif
+
+ return(1);
+}
+
+static void au1x00_halt(struct eth_device* dev){
+}
+
+int au1x00_enet_initialize(bd_t *bis){
+ struct eth_device* dev;
+
+ if ((dev = (struct eth_device*)malloc(sizeof *dev)) == NULL) {
+ puts ("malloc failed\n");
+ return 0;
+ }
+
+ memset(dev, 0, sizeof *dev);
+
+ sprintf(dev->name, "Au1X00 ethernet");
+ dev->iobase = 0;
+ dev->priv = 0;
+ dev->init = au1x00_init;
+ dev->halt = au1x00_halt;
+ dev->send = au1x00_send;
+ dev->recv = au1x00_recv;
+
+ eth_register(dev);
+
+#if (CONFIG_COMMANDS & CFG_CMD_MII)
+ miiphy_register(dev->name,
+ au1x00_miiphy_read, au1x00_miiphy_write);
+#endif
+
+ return 1;
+}
+
+#if (CONFIG_COMMANDS & CFG_CMD_MII)
+int au1x00_miiphy_read(char *devname, unsigned char addr,
+ unsigned char reg, unsigned short * value)
+{
+ volatile u32 *mii_control_reg = (volatile u32*)(ETH0_BASE+MAC_MII_CNTRL);
+ volatile u32 *mii_data_reg = (volatile u32*)(ETH0_BASE+MAC_MII_DATA);
+ u32 mii_control;
+ unsigned int timedout = 20;
+
+ while (*mii_control_reg & MAC_MII_BUSY) {
+ udelay(1000);
+ if (--timedout == 0) {
+ printf("au1x00_eth: miiphy_read busy timeout!!\n");
+ return -1;
+ }
+ }
+
+ mii_control = MAC_SET_MII_SELECT_REG(reg) |
+ MAC_SET_MII_SELECT_PHY(addr) | MAC_MII_READ;
+
+ *mii_control_reg = mii_control;
+
+ timedout = 20;
+ while (*mii_control_reg & MAC_MII_BUSY) {
+ udelay(1000);
+ if (--timedout == 0) {
+ printf("au1x00_eth: miiphy_read busy timeout!!\n");
+ return -1;
+ }
+ }
+ *value = *mii_data_reg;
+ return 0;
+}
+
+int au1x00_miiphy_write(char *devname, unsigned char addr,
+ unsigned char reg, unsigned short value)
+{
+ volatile u32 *mii_control_reg = (volatile u32*)(ETH0_BASE+MAC_MII_CNTRL);
+ volatile u32 *mii_data_reg = (volatile u32*)(ETH0_BASE+MAC_MII_DATA);
+ u32 mii_control;
+ unsigned int timedout = 20;
+
+ while (*mii_control_reg & MAC_MII_BUSY) {
+ udelay(1000);
+ if (--timedout == 0) {
+ printf("au1x00_eth: miiphy_write busy timeout!!\n");
+ return;
+ }
+ }
+
+ mii_control = MAC_SET_MII_SELECT_REG(reg) |
+ MAC_SET_MII_SELECT_PHY(addr) | MAC_MII_WRITE;
+
+ *mii_data_reg = value;
+ *mii_control_reg = mii_control;
+ return 0;
+}
+#endif /* CONFIG_COMMANDS & CFG_CMD_MII */
+
+#endif /* CONFIG_AU1X00 */
diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/au1x00_serial.c b/package/uboot-ifxmips/files/cpu/mips/danube/au1x00_serial.c
new file mode 100644
index 000000000..42c668ee3
--- /dev/null
+++ b/package/uboot-ifxmips/files/cpu/mips/danube/au1x00_serial.c
@@ -0,0 +1,135 @@
+/*
+ * AU1X00 UART support
+ *
+ * Hardcoded to UART 0 for now
+ * Speed and options also hardcoded to 115200 8N1
+ *
+ * Copyright (c) 2003 Thomas.Lange@corelatus.se
+ *
+ * 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 <config.h>
+
+#ifdef CONFIG_AU1X00
+
+#include <common.h>
+#include <asm/au1x00.h>
+
+/******************************************************************************
+*
+* serial_init - initialize a channel
+*
+* This routine initializes the number of data bits, parity
+* and set the selected baud rate. Interrupts are disabled.
+* Set the modem control signals if the option is selected.
+*
+* RETURNS: N/A
+*/
+
+int serial_init (void)
+{
+ volatile u32 *uart_fifoctl = (volatile u32*)(UART0_ADDR+UART_FCR);
+ volatile u32 *uart_enable = (volatile u32*)(UART0_ADDR+UART_ENABLE);
+
+ /* Enable clocks first */
+ *uart_enable = UART_EN_CE;
+
+ /* Then release reset */
+ /* Must release reset before setting other regs */
+ *uart_enable = UART_EN_CE|UART_EN_E;
+
+ /* Activate fifos, reset tx and rx */
+ /* Set tx trigger level to 12 */
+ *uart_fifoctl = UART_FCR_ENABLE_FIFO|UART_FCR_CLEAR_RCVR|
+ UART_FCR_CLEAR_XMIT|UART_FCR_T_TRIGGER_12;
+
+ serial_setbrg();
+
+ return 0;
+}
+
+
+void serial_setbrg (void)
+{
+ volatile u32 *uart_clk = (volatile u32*)(UART0_ADDR+UART_CLK);
+ volatile u32 *uart_lcr = (volatile u32*)(UART0_ADDR+UART_LCR);
+ volatile u32 *sys_powerctrl = (u32 *)SYS_POWERCTRL;
+ int sd;
+ int divisorx2;
+
+ /* sd is system clock divisor */
+ /* see section 10.4.5 in au1550 datasheet */
+ sd = (*sys_powerctrl & 0x03) + 2;
+
+ /* calulate 2x baudrate and round */
+ divisorx2 = ((CFG_HZ/(sd * 16 * CONFIG_BAUDRATE)));
+
+ if (divisorx2 & 0x01)
+ divisorx2 = divisorx2 + 1;
+
+ *uart_clk = divisorx2 / 2;
+
+ /* Set parity, stop bits and word length to 8N1 */
+ *uart_lcr = UART_LCR_WLEN8;
+}
+
+void serial_putc (const char c)
+{
+ volatile u32 *uart_lsr = (volatile u32*)(UART0_ADDR+UART_LSR);
+ volatile u32 *uart_tx = (volatile u32*)(UART0_ADDR+UART_TX);
+
+ if (c == '\n') serial_putc ('\r');
+
+ /* Wait for fifo to shift out some bytes */
+ while((*uart_lsr&UART_LSR_THRE)==0);
+
+ *uart_tx = (u32)c;
+}
+
+void serial_puts (const char *s)
+{
+ while (*s)
+ {
+ serial_putc (*s++);
+ }
+}
+
+int serial_getc (void)
+{
+ volatile u32 *uart_rx = (volatile u32*)(UART0_ADDR+UART_RX);
+ char c;
+
+ while (!serial_tstc());
+
+ c = (*uart_rx&0xFF);
+ return c;
+}
+
+int serial_tstc (void)
+{
+ volatile u32 *uart_lsr = (volatile u32*)(UART0_ADDR+UART_LSR);
+
+ if(*uart_lsr&UART_LSR_DR){
+ /* Data in rfifo */
+ return(1);
+ }
+ return 0;
+}
+#endif /* CONFIG_SERIAL_AU1X00 */
diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/au1x00_usb_ohci.c b/package/uboot-ifxmips/files/cpu/mips/danube/au1x00_usb_ohci.c
new file mode 100644
index 000000000..dbf72dc6f
--- /dev/null
+++ b/package/uboot-ifxmips/files/cpu/mips/danube/au1x00_usb_ohci.c
@@ -0,0 +1,1727 @@
+/*
+ * URB OHCI HCD (Host Controller Driver) for USB on the AU1x00.
+ *
+ * (C) Copyright 2003
+ * Gary Jennejohn, DENX Software Engineering <gj@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
+ *
+ * Note: Part of this code has been derived from linux
+ *
+ */
+/*
+ * IMPORTANT NOTES
+ * 1 - you MUST define LITTLEENDIAN in the configuration file for the
+ * board or this driver will NOT work!
+ * 2 - this driver is intended for use with USB Mass Storage Devices
+ * (BBB) ONLY. There is NO support for Interrupt or Isochronous pipes!
+ */
+
+#include <config.h>
+
+#if defined(CONFIG_AU1X00) && defined(CONFIG_USB_OHCI)
+
+/* #include <pci.h> no PCI on the AU1x00 */
+
+#include <common.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <asm/au1x00.h>
+#include <usb.h>
+#include "au1x00_usb_ohci.h"
+
+#define OHCI_USE_NPS /* force NoPowerSwitching mode */
+#define OHCI_VERBOSE_DEBUG /* not always helpful */
+#define OHCI_FILL_TRACE
+
+#define USBH_ENABLE_BE (1<<0)
+#define USBH_ENABLE_C (1<<1)
+#define USBH_ENABLE_E (1<<2)
+#define USBH_ENABLE_CE (1<<3)
+#define USBH_ENABLE_RD (1<<4)
+
+#ifdef LITTLEENDIAN
+#define USBH_ENABLE_INIT (USBH_ENABLE_CE | USBH_ENABLE_E | USBH_ENABLE_C)
+#else
+#define USBH_ENABLE_INIT (USBH_ENABLE_CE | USBH_ENABLE_E | USBH_ENABLE_C | USBH_ENABLE_BE)
+#endif
+
+
+/* For initializing controller (mask in an HCFS mode too) */
+#define OHCI_CONTROL_INIT \
+ (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE
+
+#undef readl
+#undef writel
+
+#define readl(a) au_readl((long)(a))
+#define writel(v,a) au_writel((v),(int)(a))
+
+#define min_t(type,x,y) ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
+
+#define DEBUG
+#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)
+#define SHOW_INFO
+#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)
+
+/* 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 *)m32_swap(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 (&regs->revision) & 0xff;
+ if (temp != 0x10)
+ dbg ("spec %d.%d", (temp >> 4), (temp & 0x0f));
+
+ temp = readl (&regs->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 (&regs->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 (&regs->intrstatus));
+ ohci_dump_intr_mask ("intrenable", readl (&regs->intrenable));
+
+ maybe_print_eds ("ed_periodcurrent", readl (&regs->ed_periodcurrent));
+
+ maybe_print_eds ("ed_controlhead", readl (&regs->ed_controlhead));
+ maybe_print_eds ("ed_controlcurrent", readl (&regs->ed_controlcurrent));
+
+ maybe_print_eds ("ed_bulkhead", readl (&regs->ed_bulkhead));
+ maybe_print_eds ("ed_bulkcurrent", readl (&regs->ed_bulkcurrent));
+
+ maybe_print_eds ("donehead", readl (&regs->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 m16_swap (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 ((long)ed, &ohci->regs->ed_controlhead);
+ } else {
+ ohci->ed_controltail->hwNextED = m32_swap (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 ((long)ed, &ohci->regs->ed_bulkhead);
+ } else {
+ ohci->ed_bulktail->hwNextED = m32_swap (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 *ed)
+{
+ ed->hwINFO |= m32_swap (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 (m32_swap (*((__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 *)m32_swap (*((__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 (m32_swap (*((__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 *)m32_swap (*((__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 = m32_swap (OHCI_ED_SKIP); /* skip ed */
+ /* dummy td; end of td list for ed */
+ td = td_alloc (usb_dev);
+ ed->hwTailP = m32_swap (td);
+ ed->hwHeadP = ed->hwTailP;
+ ed->state = ED_UNLINK;
+ ed->type = usb_pipetype (pipe);
+ ohci_dev.ed_cnt++;
+ }
+
+ ed->hwINFO = m32_swap (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 *)(m32_swap (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 (1 || ((usb_pipetype(urb_priv->pipe) == PIPE_BULK) && usb_pipeout(urb_priv->pipe))) {
+ for (i = 0; i < len; i++)
+ printf("td->data[%d] %#2x\n",i, ((unsigned char *)(td->data+0x80000000))[i]);
+ }
+#endif
+ if (!len)
+ data = 0;
+
+ td->hwINFO = m32_swap (info);
+ td->hwCBP = m32_swap (data);
+ if (data)
+ td->hwBE = m32_swap (data + len - 1);
+ else
+ td->hwBE = 0;
+ td->hwNextTD = m32_swap (td_pt);
+ td->hwPSW [0] = m16_swap (((__u32)data & 0x0FFF) | 0xE000);
+
+ /* append to queue */
+ td->ed->hwTailP = td->hwNextTD;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* prepare all TDs of a transfer */
+
+#define kseg_to_phys(x) ((void *)((__u32)(x) - 0x80000000))
+
+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 = kseg_to_phys(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, kseg_to_phys(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 = m32_swap (td->hwINFO);
+ tdBE = m32_swap (td->hwBE);
+ tdCBP = m32_swap (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 = m32_swap (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 (m32_swap (td_list->hwINFO))) {
+ lurb_priv = &urb_priv;
+ dbg(" USB-error/status: %x : %p",
+ TD_CC_GET (m32_swap (td_list->hwINFO)), td_list);
+ if (td_list->ed->hwHeadP & m32_swap (0x1)) {
+ if (lurb_priv && ((td_list->index + 1) < lurb_priv->length)) {
+ td_list->ed->hwHeadP =
+ (lurb_priv->td[lurb_priv->length - 1]->hwNextTD & m32_swap (0xfffffff0)) |
+ (td_list->ed->hwHeadP & m32_swap (0x2));
+ lurb_priv->td_cnt += lurb_priv->length - td_list->index - 1;
+ } else
+ td_list->ed->hwHeadP &= m32_swap (0xfffffff2);
+ }
+ }
+
+ td_list->next_dl_td = td_rev;
+ td_rev = td_list;
+ td_list_hc = m32_swap (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 = 0;
+ /* 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 = m32_swap (td_list->hwINFO);
+
+ ed = td_list->ed;
+
+ dl_transfer_length(td_list);
+
+ /* error code of transfer */
+ cc = TD_CC_GET (tdINFO);
+ if (cc != 0) {
+ dbg("ConditionCode %#x", cc);
+ stat = cc_to_error[cc];
+ }
+
+ if (ed->state != ED_NEW) {
+ edHeadP = m32_swap (ed->hwHeadP) & 0xfffffff0;
+ edTailP = m32_swap (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));
+#else
+ wait_ms(1);
+#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);
+#else
+ wait_ms(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)*/);
+#else
+ wait_ms(1);
+#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));
+#else
+ wait_ms(1);
+#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;
+ }
+
+ wait_ms(10);
+ /* ohci_dump_status(&gohci); */
+
+ /* 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;
+
+ timeout *= 4;
+ /* 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) {
+ udelay(250); /* 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));
+#else
+ wait_ms(1);
+#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));
+#else
+ wait_ms(1);
+#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) */
+ writel (0, &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) && !(m32_swap (ohci->hcca->done_head) & 0x01)) {
+ ints = OHCI_INTR_WDH;
+ } else {
+ ints = readl (&regs->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);
+#else
+ wait_ms(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) {
+ wait_ms(1);
+ writel (OHCI_INTR_WDH, &regs->intrdisable);
+ stat = dl_done_list (&gohci, dl_reverse_done_list (&gohci));
+ writel (OHCI_INTR_WDH, &regs->intrenable);
+ }
+
+ if (ints & OHCI_INTR_SO) {
+ dbg("USB Schedule overrun\n");
+ writel (OHCI_INTR_SO, &regs->intrenable);
+ stat = -1;
+ }
+
+ /* FIXME: this assumes SOF (1/ms) interrupts don't get lost... */
+ if (ints & OHCI_INTR_SF) {
+ unsigned int frame = m16_swap (ohci->hcca->frame_no) & 1;
+ wait_ms(1);
+ writel (OHCI_INTR_SF, &regs->intrdisable);
+ if (ohci->ed_rm_list[frame] != NULL)
+ writel (OHCI_INTR_SF, &regs->intrenable);
+ stat = 0xff;
+ }
+
+ writel (ints, &regs->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);
+}
+
+/*-------------------------------------------------------------------------*/
+
+#define __read_32bit_c0_register(source, sel) \
+({ int __res; \
+ if (sel == 0) \
+ __asm__ __volatile__( \
+ "mfc0\t%0, " #source "\n\t" \
+ : "=r" (__res)); \
+ else \
+ __asm__ __volatile__( \
+ ".set\tmips32\n\t" \
+ "mfc0\t%0, " #source ", " #sel "\n\t" \
+ ".set\tmips0\n\t" \
+ : "=r" (__res)); \
+ __res; \
+})
+
+#define read_c0_prid() __read_32bit_c0_register($15, 0)
+
+/*
+ * low level initalisation routine, called from usb.c
+ */
+static char ohci_inited = 0;
+
+int usb_lowlevel_init(void)
+{
+ u32 pin_func;
+ u32 sys_freqctrl, sys_clksrc;
+ u32 prid = read_c0_prid();
+
+ dbg("in usb_lowlevel_init\n");
+
+ /* zero and disable FREQ2 */
+ sys_freqctrl = au_readl(SYS_FREQCTRL0);
+ sys_freqctrl &= ~0xFFF00000;
+ au_writel(sys_freqctrl, SYS_FREQCTRL0);
+
+ /* zero and disable USBH/USBD clocks */
+ sys_clksrc = au_readl(SYS_CLKSRC);
+ sys_clksrc &= ~0x00007FE0;
+ au_writel(sys_clksrc, SYS_CLKSRC);
+
+ sys_freqctrl = au_readl(SYS_FREQCTRL0);
+ sys_freqctrl &= ~0xFFF00000;
+
+ sys_clksrc = au_readl(SYS_CLKSRC);
+ sys_clksrc &= ~0x00007FE0;
+
+ switch (prid & 0x000000FF) {
+ case 0x00: /* DA */
+ case 0x01: /* HA */
+ case 0x02: /* HB */
+ /* CPU core freq to 48MHz to slow it way down... */
+ au_writel(4, SYS_CPUPLL);
+
+ /*
+ * Setup 48MHz FREQ2 from CPUPLL for USB Host
+ */
+ /* FRDIV2=3 -> div by 8 of 384MHz -> 48MHz */
+ sys_freqctrl |= ((3<<22) | (1<<21) | (0<<20));
+ au_writel(sys_freqctrl, SYS_FREQCTRL0);
+
+ /* CPU core freq to 384MHz */
+ au_writel(0x20, SYS_CPUPLL);
+
+ printf("Au1000: 48MHz OHCI workaround enabled\n");
+ break;
+
+ default: /* HC and newer */
+ /* FREQ2 = aux/2 = 48 MHz */
+ sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20));
+ au_writel(sys_freqctrl, SYS_FREQCTRL0);
+ break;
+ }
+
+ /*
+ * Route 48MHz FREQ2 into USB Host and/or Device
+ */
+ sys_clksrc |= ((4<<12) | (0<<11) | (0<<10));
+ au_writel(sys_clksrc, SYS_CLKSRC);
+
+ /* configure pins GPIO[14:9] as GPIO */
+ pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8080);
+
+ au_writel(pin_func, SYS_PINFUNC);
+ au_writel(0x2800, SYS_TRIOUTCLR);
+ au_writel(0x0030, SYS_OUTPUTCLR);
+
+ dbg("OHCI board setup complete\n");
+
+ /* enable host controller */
+ au_writel(USBH_ENABLE_CE, USB_HOST_CONFIG);
+ udelay(1000);
+ au_writel(USBH_ENABLE_INIT, USB_HOST_CONFIG);
+ udelay(1000);
+
+ /* wait for reset complete (read register twice; see au1500 errata) */
+ while (au_readl(USB_HOST_CONFIG),
+ !(au_readl(USB_HOST_CONFIG) & USBH_ENABLE_RD))
+ udelay(1000);
+
+ dbg("OHCI clock running\n");
+
+ 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 *)(USB_OHCI_BASE | 0xA0000000);
+
+ gohci.flags = 0;
+ gohci.slot_name = "au1x00";
+
+ dbg("OHCI revision: 0x%08x\n"
+ " RH: a: 0x%08x b: 0x%08x\n",
+ readl(&gohci.regs->revision),
+ readl(&gohci.regs->roothub.a), readl(&gohci.regs->roothub.b));
+
+ if (hc_reset (&gohci) < 0)
+ goto errout;
+
+ /* FIXME this is a second HC reset; why?? */
+ writel (gohci.hc_control = OHCI_USB_RESET, &gohci.regs->control);
+ wait_ms (10);
+
+ if (hc_start (&gohci) < 0)
+ goto errout;
+
+#ifdef DEBUG
+ ohci_dump (&gohci, 1);
+#else
+ wait_ms(1);
+#endif
+ ohci_inited = 1;
+ return 0;
+
+ errout:
+ err("OHCI initialization error\n");
+ hc_release_ohci (&gohci);
+ /* Initialization failed */
+ au_writel(readl(USB_HOST_CONFIG) & ~USBH_ENABLE_CE, USB_HOST_CONFIG);
+ return -1;
+}
+
+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);
+ /* may not want to do this */
+ /* Disable clock */
+ au_writel(readl(USB_HOST_CONFIG) & ~USBH_ENABLE_CE, USB_HOST_CONFIG);
+ return 0;
+}
+
+#endif /* CONFIG_USB_OHCI */
diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/au1x00_usb_ohci.h b/package/uboot-ifxmips/files/cpu/mips/danube/au1x00_usb_ohci.h
new file mode 100644
index 000000000..4ef06ffde
--- /dev/null
+++ b/package/uboot-ifxmips/files/cpu/mips/danube/au1x00_usb_ohci.h
@@ -0,0 +1,416 @@
+/*
+ * URB OHCI HCD (Host Controller Driver) for USB.
+ *
+ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ * (C) Copyright 2000-2001 David Brownell <dbrownell@users.sourceforge.net>
+ *
+ * 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 */
+ __u16 frame_no; /* current frame number */
+ __u16 pad1; /* set to 0 on each frame_no change */
+ __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/package/uboot-ifxmips/files/cpu/mips/danube/cache.S b/package/uboot-ifxmips/files/cpu/mips/danube/cache.S
new file mode 100644
index 000000000..9a3978447
--- /dev/null
+++ b/package/uboot-ifxmips/files/cpu/mips/danube/cache.S
@@ -0,0 +1,278 @@
+/*
+ * Cache-handling routined for MIPS 4K CPUs
+ *
+ * Copyright (c) 2003 Wolfgang Denk <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 <config.h>
+#include <version.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/cacheops.h>
+#if defined(CONFIG_IFX_MIPS)
+# include "ifx_cache.S"
+#endif
+
+ /* 16KB is the maximum size of instruction and data caches on
+ * MIPS 4K.
+ */
+#define MIPS_MAX_CACHE_SIZE 0x4000
+
+
+/*
+ * cacheop macro to automate cache operations
+ * first some helpers...
+ */
+#define _mincache(size, maxsize) \
+ bltu size,maxsize,9f ; \
+ move size,maxsize ; \
+9:
+
+#define _align(minaddr, maxaddr, linesize) \
+ .set noat ; \
+ subu AT,linesize,1 ; \
+ not AT ; \
+ and minaddr,AT ; \
+ addu maxaddr,-1 ; \
+ and maxaddr,AT ; \
+ .set at
+
+/* general operations */
+#define doop1(op1) \
+ cache op1,0(a0)
+#define doop2(op1, op2) \
+ cache op1,0(a0) ; \
+ nop ; \
+ cache op2,0(a0)
+
+/* specials for cache initialisation */
+#define doop1lw(op1) \
+ lw zero,0(a0)
+#define doop1lw1(op1) \
+ cache op1,0(a0) ; \
+ lw zero,0(a0) ; \
+ cache op1,0(a0)
+#define doop121(op1,op2) \
+ cache op1,0(a0) ; \
+ nop; \
+ cache op2,0(a0) ; \
+ nop; \
+ cache op1,0(a0)
+
+#define _oploopn(minaddr, maxaddr, linesize, tag, ops) \
+ .set noreorder ; \
+10: doop##tag##ops ; \
+ bne minaddr,maxaddr,10b ; \
+ add minaddr,linesize ; \
+ .set reorder
+
+/* finally the cache operation macros */
+#define vcacheopn(kva, n, cacheSize, cacheLineSize, tag, ops) \
+ blez n,11f ; \
+ addu n,kva ; \
+ _align(kva, n, cacheLineSize) ; \
+ _oploopn(kva, n, cacheLineSize, tag, ops) ; \
+11:
+
+#define icacheopn(kva, n, cacheSize, cacheLineSize, tag, ops) \
+ _mincache(n, cacheSize); \
+ blez n,11f ; \
+ addu n,kva ; \
+ _align(kva, n, cacheLineSize) ; \
+ _oploopn(kva, n, cacheLineSize, tag, ops) ; \
+11:
+
+#define vcacheop(kva, n, cacheSize, cacheLineSize, op) \
+ vcacheopn(kva, n, cacheSize, cacheLineSize, 1, (op))
+
+#define icacheop(kva, n, cacheSize, cacheLineSize, op) \
+ icacheopn(kva, n, cacheSize, cacheLineSize, 1, (op))
+
+/*******************************************************************************
+*
+* mips_cache_reset - low level initialisation of the primary caches
+*
+* This routine initialises the primary caches to ensure that they
+* have good parity. It must be called by the ROM before any cached locations
+* are used to prevent the possibility of data with bad parity being written to
+* memory.
+* To initialise the instruction cache it is essential that a source of data
+* with good parity is available. This routine
+* will initialise an area of memory starting at location zero to be used as
+* a source of parity.
+*
+* RETURNS: N/A
+*
+*/
+ .globl mips_cache_reset
+ .ent mips_cache_reset
+mips_cache_reset:
+
+ li t2, CFG_ICACHE_SIZE
+ li t3, CFG_DCACHE_SIZE
+ li t4, CFG_CACHELINE_SIZE
+ move t5, t4
+
+
+ li v0, MIPS_MAX_CACHE_SIZE
+
+ /* Now clear that much memory starting from zero.
+ */
+
+ li a0, KSEG1
+ addu a1, a0, v0
+
+2: sw zero, 0(a0)
+ sw zero, 4(a0)
+ sw zero, 8(a0)
+ sw zero, 12(a0)
+ sw zero, 16(a0)
+ sw zero, 20(a0)
+ sw zero, 24(a0)
+ sw zero, 28(a0)
+ addu a0, 32
+ bltu a0, a1, 2b
+
+ /* Set invalid tag.
+ */
+
+ mtc0 zero, CP0_TAGLO
+#if defined(CONFIG_IFX_MIPS) && defined(IFX_CACHE_EXTRA_INVALID_TAG)
+ IFX_CACHE_EXTRA_INVALID_TAG
+#endif
+
+ /*
+ * The caches are probably in an indeterminate state,
+ * so we force good parity into them by doing an
+ * invalidate, load/fill, invalidate for each line.
+ */
+
+ /* Assume bottom of RAM will generate good parity for the cache.
+ */
+
+ li a0, K0BASE
+ move a2, t2 # icacheSize
+ move a3, t4 # icacheLineSize
+ move a1, a2
+ icacheopn(a0,a1,a2,a3,121,(Index_Store_Tag_I,Fill))
+
+#if defined(CONFIG_IFX_MIPS) && defined(IFX_CACHE_EXTRA_OPERATION)
+ IFX_CACHE_EXTRA_OPERATION
+#else
+ /* To support Orion/R4600, we initialise the data cache in 3 passes.
+ */
+
+ /* 1: initialise dcache tags.
+ */
+
+ li a0, K0BASE
+ move a2, t3 # dcacheSize
+ move a3, t5 # dcacheLineSize
+ move a1, a2
+ icacheop(a0,a1,a2,a3,Index_Store_Tag_D)
+
+ /* 2: fill dcache.
+ */
+
+ li a0, K0BASE
+ move a2, t3 # dcacheSize
+ move a3, t5 # dcacheLineSize
+ move a1, a2
+ icacheopn(a0,a1,a2,a3,1lw,(dummy))
+
+ /* 3: clear dcache tags.
+ */
+
+ li a0, K0BASE
+ move a2, t3 # dcacheSize
+ move a3, t5 # dcacheLineSize
+ move a1, a2
+ icacheop(a0,a1,a2,a3,Index_Store_Tag_D)
+#endif
+
+ j ra
+ .end mips_cache_reset
+
+
+/*******************************************************************************
+*
+* dcache_status - get cache status
+*
+* RETURNS: 0 - cache disabled; 1 - cache enabled
+*
+*/
+ .globl dcache_status
+ .ent dcache_status
+dcache_status:
+
+ mfc0 v0, CP0_CONFIG
+ andi v0, v0, 1
+ j ra
+
+ .end dcache_status
+
+/*******************************************************************************
+*
+* dcache_disable - disable cache
+*
+* RETURNS: N/A
+*
+*/
+ .globl dcache_disable
+ .ent dcache_disable
+dcache_disable:
+
+ mfc0 t0, CP0_CONFIG
+ li t1, -8
+ and t0, t0, t1
+ ori t0, t0, CONF_CM_UNCACHED
+ mtc0 t0, CP0_CONFIG
+ j ra
+
+ .end dcache_disable
+
+
+/*******************************************************************************
+*
+* mips_cache_lock - lock RAM area pointed to by a0 in cache.
+*
+* RETURNS: N/A
+*
+*/
+#if defined(CONFIG_PURPLE)
+# define CACHE_LOCK_SIZE (CFG_DCACHE_SIZE/2)
+#else
+# define CACHE_LOCK_SIZE (CFG_DCACHE_SIZE)
+#endif
+ .globl mips_cache_lock
+ .ent mips_cache_lock
+mips_cache_lock:
+ li a1, K0BASE - CACHE_LOCK_SIZE
+ addu a0, a1
+ li a2, CACHE_LOCK_SIZE
+ li a3, CFG_CACHELINE_SIZE
+ move a1, a2
+ icacheop(a0,a1,a2,a3,0x1d)
+
+ j ra
+ .end mips_cache_lock
diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/config.mk b/package/uboot-ifxmips/files/cpu/mips/danube/config.mk
new file mode 100644
index 000000000..3414ad8a7
--- /dev/null
+++ b/package/uboot-ifxmips/files/cpu/mips/danube/config.mk
@@ -0,0 +1,53 @@
+#
+# (C) Copyright 2003
+# 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
+#
+v=$(shell \
+$(CROSS_COMPILE)as --version|grep "GNU assembler"|awk '{print $$3}'|awk -F . '{print $$2}')
+
+ifndef PLATFORM_CPU
+PLATFORM_CPU = mips32r2
+endif
+
+MIPSFLAGS=$(shell \
+if [ "$v" -lt "14" ]; then \
+ echo "-mcpu=$(PLATFORM_CPU)"; \
+else \
+ echo "-march=$(PLATFORM_CPU) -mtune=$(PLATFORM_CPU)"; \
+fi)
+
+ifeq ($(CROSS_COMPILE_UCLIBC),1)
+ifneq (,$(findstring mipsel,$(CROSS_COMIPLE)))
+ENDIANNESS = -el
+else
+ENDIANNESS = -eb
+endif
+else
+ifneq (,$(findstring 4KCle,$(CROSS_COMPILE)))
+ENDIANNESS = -EL
+else
+ENDIANNESS = -EB
+endif
+endif
+
+MIPSFLAGS += $(ENDIANNESS) -mabicalls
+
+PLATFORM_CPPFLAGS += $(MIPSFLAGS)
diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/cpu.c b/package/uboot-ifxmips/files/cpu/mips/danube/cpu.c
new file mode 100644
index 000000000..b9f90ce0c
--- /dev/null
+++ b/package/uboot-ifxmips/files/cpu/mips/danube/cpu.c
@@ -0,0 +1,61 @@
+/*
+ * (C) Copyright 2003
+ * 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 <common.h>
+#include <command.h>
+#if defined(CONFIG_INCA_IP)
+# include <asm/inca-ip.h>
+#elif defined(CONFIG_IFX_MIPS)
+# include <asm/danube.h>
+# include "ifx_cpu.c"
+#endif
+#include <asm/mipsregs.h>
+
+int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+#if defined(CONFIG_INCA_IP)
+ *INCA_IP_WDT_RST_REQ = 0x3f;
+#elif defined(CONFIG_PURPLE) || defined(CONFIG_TB0229)
+ void (*f)(void) = (void *) 0xbfc00000;
+
+ f();
+#elif defined(CONFIG_IFX_MIPS)
+ IFX_CPU_RESET;
+#endif
+ fprintf(stderr, "*** reset failed ***\n");
+ return 0;
+}
+
+void flush_cache (ulong start_addr, ulong size)
+{
+
+}
+
+void write_one_tlb( int index, u32 pagemask, u32 hi, u32 low0, u32 low1 ){
+ write_32bit_cp0_register(CP0_ENTRYLO0, low0);
+ write_32bit_cp0_register(CP0_PAGEMASK, pagemask);
+ write_32bit_cp0_register(CP0_ENTRYLO1, low1);
+ write_32bit_cp0_register(CP0_ENTRYHI, hi);
+ write_32bit_cp0_register(CP0_INDEX, index);
+ tlb_write_indexed();
+}
diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/ifx_asc.c b/package/uboot-ifxmips/files/cpu/mips/danube/ifx_asc.c
new file mode 100644
index 000000000..52c6cb271
--- /dev/null
+++ b/package/uboot-ifxmips/files/cpu/mips/danube/ifx_asc.c
@@ -0,0 +1,257 @@
+/*****************************************************************************
+ * DANUBE BootROM
+ * Copyright (c) 2005, Infineon Technologies AG, All rights reserved
+ * IFAP DC COM SD
+ *****************************************************************************/
+
+#include <config.h>
+//#include <lib.h>
+#include <asm/danube.h>
+#include <asm/addrspace.h>
+#include <asm/ifx_asc.h>
+
+
+#define ASC_FIFO_PRESENT
+#define SET_BIT(reg, mask) reg |= (mask)
+#define CLEAR_BIT(reg, mask) reg &= (~mask)
+#define CLEAR_BITS(reg, mask) CLEAR_BIT(reg, mask)
+#define SET_BITS(reg, mask) SET_BIT(reg, mask)
+#define SET_BITFIELD(reg, mask, off, val) {reg &= (~mask); reg |= (val << off);}
+
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned long u32;
+typedef signed long s32;
+typedef unsigned int uint;
+typedef unsigned long ulong;
+typedef volatile unsigned short vuint;
+
+
+
+void serial_setbrg (void);
+
+/*TODO: undefine this !!!*/
+#undef DEBUG_ASC_RAW
+#ifdef DEBUG_ASC_RAW
+#define DEBUG_ASC_RAW_RX_BUF 0xA0800000
+#define DEBUG_ASC_RAW_TX_BUF 0xA0900000
+#endif
+
+static volatile DanubeAsc_t *pAsc = (DanubeAsc_t *)DANUBE_ASC1;
+
+typedef struct{
+ u16 fdv; /* 0~511 fractional divider value*/
+ u16 reload; /* 13 bit reload value*/
+} ifx_asc_baud_reg_t;
+
+#ifdef ON_VENUS
+/*9600 @1.25M rel 00.08*/
+//#define FDV 503
+//#define RELOAD 7
+/*9600 @0.625M rel final00.01 & rtl_freeze*/
+#define FDV 503
+#define RELOAD 3
+/* first index is DDR_SEL, second index is FPI_SEL */
+#endif
+static ifx_asc_baud_reg_t g_danube_asc_baud[4][2] =
+{
+#ifdef ON_VENUS
+ {{503,3},{503,3}}, /* 1152000 @ 166.67M and half*/
+ {{503,3},{503,3}}, /* 1152000 @ 133.3M and half*/
+ {{503,3},{503,3}}, /* 1152000 @ 111.11M and half*/
+ {{503.3},{503,3}} /* 1152000 @ 83.33M and half*/
+#else
+/* TAPEOUT table */
+ {{436,76},{419,36}}, /* 1152000 @ 166.67M and half*/
+ {{453,63},{453,31}}, /* 1152000 @ 133.3M and half*/
+ {{501,58},{510,29}}, /* 1152000 @ 111.11M and half*/
+ {{419.36},{453,19}} /* 1152000 @ 83.33M and half*/
+#endif
+};
+/******************************************************************************
+*
+* asc_init - initialize a Danube ASC channel
+*
+* This routine initializes the number of data bits, parity
+* and set the selected baud rate. Interrupts are disabled.
+* Set the modem control signals if the option is selected.
+*
+* RETURNS: N/A
+*/
+
+int serial_init (void)
+{
+
+ /* and we have to set CLC register*/
+ CLEAR_BIT(pAsc->asc_clc, ASCCLC_DISS);
+ SET_BITFIELD(pAsc->asc_clc, ASCCLC_RMCMASK, ASCCLC_RMCOFFSET, 0x0001);
+
+ /* initialy we are in async mode */
+ pAsc->asc_con = ASCCON_M_8ASYNC;
+
+ /* select input port */
+ pAsc->asc_pisel = (CONSOLE_TTY & 0x1);
+
+ /* TXFIFO's filling level */
+ SET_BITFIELD(pAsc->asc_txfcon, ASCTXFCON_TXFITLMASK,
+ ASCTXFCON_TXFITLOFF, DANUBEASC_TXFIFO_FL);
+ /* enable TXFIFO */
+ SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXFEN);
+
+ /* RXFIFO's filling level */
+ SET_BITFIELD(pAsc->asc_txfcon, ASCRXFCON_RXFITLMASK,
+ ASCRXFCON_RXFITLOFF, DANUBEASC_RXFIFO_FL);
+ /* enable RXFIFO */
+ SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXFEN);
+
+ /* set baud rate */
+ serial_setbrg();
+
+ /* enable error signals & Receiver enable */
+ SET_BIT(pAsc->asc_whbstate, ASCWHBSTATE_SETREN|ASCCON_FEN|ASCCON_TOEN|ASCCON_ROEN);
+
+ return 0;
+}
+
+void serial_setbrg (void)
+{
+ u32 uiReloadValue, fdv;
+
+#if defined(ON_IKOS)
+ /*1200 @77K */
+ fdv=472;
+ uiReloadValue=5;
+#else
+ /*venus & tapeout */
+ u32 ddr_sel,fpi_sel;
+ ddr_sel = (* DANUBE_CGU_SYS) & 0x3;
+ fpi_sel = ((* DANUBE_CGU_SYS) & 0x40)?1:0;
+ fdv= g_danube_asc_baud[ddr_sel][fpi_sel].fdv;
+ uiReloadValue=g_danube_asc_baud[ddr_sel][fpi_sel].reload;
+#endif //ON_IKOS
+ /* Disable Baud Rate Generator; BG should only be written when R=0 */
+ CLEAR_BIT(pAsc->asc_con, ASCCON_R);
+
+ /* Enable Fractional Divider */
+ SET_BIT(pAsc->asc_con, ASCCON_FDE); /* FDE = 1 */
+
+ /* Set fractional divider value */
+ pAsc->asc_fdv = fdv & ASCFDV_VALUE_MASK;
+
+ /* Set reload value in BG */
+ pAsc->asc_bg = uiReloadValue;
+
+ /* Enable Baud Rate Generator */
+ SET_BIT(pAsc->asc_con, ASCCON_R); /* R = 1 */
+}
+
+
+void serial_putc (const char c)
+{
+ u32 txFl = 0;
+#ifdef DEBUG_ASC_RAW
+ static u8 * debug = (u8 *) DEBUG_ASC_RAW_TX_BUF;
+ *debug++=c;
+#endif
+ if (c == '\n')
+ serial_putc ('\r');
+ /* check do we have a free space in the TX FIFO */
+ /* get current filling level */
+ do
+ {
+ txFl = ( pAsc->asc_fstat & ASCFSTAT_TXFFLMASK ) >> ASCFSTAT_TXFFLOFF;
+ }
+ while ( txFl == DANUBEASC_TXFIFO_FULL );
+
+ pAsc->asc_tbuf = c; /* write char to Transmit Buffer Register */
+
+ /* check for errors */
+ if ( pAsc->asc_state & ASCSTATE_TOE )
+ {
+ SET_BIT(pAsc->asc_whbstate, ASCWHBSTATE_CLRTOE);
+ return;
+ }
+}
+
+void serial_puts (const char *s)
+{
+ while (*s)
+ {
+ serial_putc (*s++);
+ }
+}
+
+int asc_inb(int timeout)
+{
+ u32 symbol_mask;
+ char c;
+ while ((pAsc->asc_fstat & ASCFSTAT_RXFFLMASK) == 0 ) {
+ }
+ symbol_mask = ((ASC_OPTIONS & ASCOPT_CSIZE) == ASCOPT_CS7) ? (0x7f) : (0xff);
+ c = (char)(pAsc->asc_rbuf & symbol_mask);
+ return (c);
+}
+
+int serial_getc (void)
+{
+ char c;
+ while ((pAsc->asc_fstat & ASCFSTAT_RXFFLMASK) == 0 );
+ c = (char)(pAsc->asc_rbuf & 0xff);
+
+#ifdef DEBUG_ASC_RAW
+ static u8* debug=(u8*)(DEBUG_ASC_RAW_RX_BUF);
+ *debug++=c;
+#endif
+ return c;
+}
+
+
+
+int serial_tstc (void)
+{
+ int res = 1;
+
+#ifdef ASC_FIFO_PRESENT
+ if ( (pAsc->asc_fstat & ASCFSTAT_RXFFLMASK) == 0 )
+ {
+ res = 0;
+ }
+#else
+ if (!(*(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) &
+ FBS_ISR_AR))
+
+ {
+ res = 0;
+ }
+#endif
+#if 0
+ else if ( pAsc->asc_con & ASCCON_FE )
+ {
+ SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRFE);
+ res = 0;
+ }
+ else if ( pAsc->asc_con & ASCCON_PE )
+ {
+ SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRPE);
+ res = 0;
+ }
+ else if ( pAsc->asc_con & ASCCON_OE )
+ {
+ SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE);
+ res = 0;
+ }
+#endif
+ return res;
+}
+
+
+int serial_start(void)
+{
+ return 1;
+}
+
+int serial_stop(void)
+{
+ return 1;
+}
diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/ifx_cache.S b/package/uboot-ifxmips/files/cpu/mips/danube/ifx_cache.S
new file mode 100644
index 000000000..fc482dcd6
--- /dev/null
+++ b/package/uboot-ifxmips/files/cpu/mips/danube/ifx_cache.S
@@ -0,0 +1,60 @@
+
+#define IFX_CACHE_EXTRA_INVALID_TAG \
+ mtc0 zero, CP0_TAGLO, 1; \
+ mtc0 zero, CP0_TAGLO, 2; \
+ mtc0 zero, CP0_TAGLO, 3; \
+ mtc0 zero, CP0_TAGLO, 4;
+
+#define IFX_CACHE_EXTRA_OPERATION \
+ /* set WST bit */ \
+ mfc0 a0, CP0_ECC; \
+ li a1, ECCF_WST; \
+ or a0, a1; \
+ mtc0 a0, CP0_ECC; \
+ \
+ li a0, K0BASE; \
+ move a2, t2; /* icacheSize */ \
+ move a3, t4; /* icacheLineSize */ \
+ move a1, a2; \
+ icacheop(a0,a1,a2,a3,(Index_Store_Tag_I)); \
+ \
+ /* clear WST bit */ \
+ mfc0 a0, CP0_ECC; \
+ li a1, ~ECCF_WST; \
+ and a0, a1; \
+ mtc0 a0, CP0_ECC; \
+ \
+ /* 1: initialise dcache tags. */ \
+ \
+ /* cache line size */ \
+ li a2, CFG_CACHELINE_SIZE; \
+ /* kseg0 mem address */ \
+ li a1, 0; \
+ li a3, CFG_CACHE_SETS * CFG_CACHE_WAYS; \
+1: \
+ /* store tag (invalid, not locked) */ \
+ cache 0x8, 0(a1); \
+ cache 0x9, 0(a1); \
+ \
+ add a3, -1; \
+ bne a3, zero, 1b; \
+ add a1, a2; \
+ \
+ /* set WST bit */ \
+ mfc0 a0, CP0_ECC; \
+ li a1, ECCF_WST; \
+ or a0, a1; \
+ mtc0 a0, CP0_ECC; \
+ \
+ li a0, K0BASE; \
+ move a2, t3; /* dcacheSize */ \
+ move a3, t5; /* dcacheLineSize */ \
+ move a1, a2; \
+ icacheop(a0,a1,a2,a3,(Index_Store_Tag_D)); \
+ \
+ /* clear WST bit */ \
+ mfc0 a0, CP0_ECC; \
+ li a1, ~ECCF_WST; \
+ and a0, a1; \
+ mtc0 a0, CP0_ECC;
+
diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/ifx_cgu.c b/package/uboot-ifxmips/files/cpu/mips/danube/ifx_cgu.c
new file mode 100644
index 000000000..3fe13dde2
--- /dev/null
+++ b/package/uboot-ifxmips/files/cpu/mips/danube/ifx_cgu.c
@@ -0,0 +1,1086 @@
+/*
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * ########################################################################
+ *
+ * danube_cgu.c
+ *
+ * Description:
+ * device driver of clock generation unit of Danube chip
+ * Author:
+ * Samuels Xu Liang
+ * Created:
+ * 19 Jul 2005
+ * History & Modification Tag:
+ * ___________________________________________________________________________
+ * | Tag | Comments | Modifier & Time |
+ * |--------+---------------------------------------------+------------------|
+ * | S0.0 | First version of this driver and the tag is | Samuels Xu Liang |
+ * | | implied. | 19 Jul 2005 |
+ * ---------------------------------------------------------------------------
+ *
+ */
+
+
+/*
+ * ####################################
+ * Head File
+ * ####################################
+ */
+
+/*
+ * Common Head File
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <asm/unistd.h>
+#include <asm/irq.h>
+#include <linux/errno.h>
+
+/*
+ * Chip Specific Head File
+ */
+#include "ifx_cgu.h"
+
+
+/*
+ * ####################################
+ * Definition
+ * ####################################
+ */
+
+#define DEBUG_ON_AMAZON 1
+#define DEBUG_PRINT_INFO 1
+
+/*
+ * Frequency of Clock Direct Feed from The Analog Line Driver Chip
+ */
+#define BASIC_INPUT_CLOCK_FREQUENCY 35328000
+
+/*
+ * Bits Operation
+ */
+#define GET_BITS(x, msb, lsb) (((x) & ((1 << ((msb) + 1)) - 1)) >> (lsb))
+#define SET_BITS(x, msb, lsb, value) (((x) & ~(((1 << ((msb) + 1)) - 1) ^ ((1 << (lsb)) - 1))) | (((value) & ((1 << (1 + (msb) - (lsb))) - 1)) << (lsb)))
+
+/*
+ * CGU Register Mapping
+ */
+#define DANUBE_CGU (KSEG1 + 0x1F103000)
+#define DANUBE_CGU_DIV ((volatile u32*)(DANUBE_CGU + 0x0000))
+#define DANUBE_CGU_PLL_NMK0 ((volatile u32*)(DANUBE_CGU + 0x0004))
+#define DANUBE_CGU_PLL_SR0 ((volatile u32*)(DANUBE_CGU + 0x0008))
+#define DANUBE_CGU_PLL_NMK1 ((volatile u32*)(DANUBE_CGU + 0x000C))
+#define DANUBE_CGU_PLL_SR1 ((volatile u32*)(DANUBE_CGU + 0x0010))
+#define DANUBE_CGU_PLL_SR2 ((volatile u32*)(DANUBE_CGU + 0x0014))
+#define DANUBE_CGU_IF_CLK ((volatile u32*)(DANUBE_CGU + 0x0018))
+#define DANUBE_CGU_OSC_CTRL ((volatile u32*)(DANUBE_CGU + 0x001C))
+#define DANUBE_CGU_SMD ((volatile u32*)(DANUBE_CGU + 0x0020))
+#define DANUBE_CGU_CRD ((volatile u32*)(DANUBE_CGU + 0x0024))
+#define DANUBE_CGU_CT1SR ((volatile u32*)(DANUBE_CGU + 0x0028))
+#define DANUBE_CGU_CT2SR ((volatile u32*)(DANUBE_CGU + 0x002C))
+#define DANUBE_CGU_PCMCR ((volatile u32*)(DANUBE_CGU + 0x0030))
+#define DANUBE_CGU_MUX ((volatile u32*)(DANUBE_CGU + 0x0034))
+
+/*
+ * CGU Divider Register
+ */
+#define CGU_DIV_SFTR (*DANUBE_CGU_DIV & (1 << 31))
+#define CGU_DIV_DIVE (*DANUBE_CGU_DIV & (1 << 16))
+#define CGU_DIV_IOR GET_BITS(*DANUBE_CGU_DIV, 5, 4)
+#define CGU_DIV_FKS GET_BITS(*DANUBE_CGU_DIV, 3, 2)
+#define CGU_DIV_FBS GET_BITS(*DANUBE_CGU_DIV, 1, 0)
+
+/*
+ * CGU PLL0 NMK Register
+ */
+#define CGU_PLL_NMK0_PLLN ((*DANUBE_CGU_PLL_NMK0 & (0xFFFFFFFF ^ ((1 << 24) - 1))) >> 24)
+#define CGU_PLL_NMK0_PLLM GET_BITS(*DANUBE_CGU_PLL_NMK0, 23, 20)
+#define CGU_PLL_NMK0_PLLK GET_BITS(*DANUBE_CGU_PLL_NMK0, 19, 0)
+
+/*
+ * CGU PLL0 Status Register
+ */
+#define CGU_PLL_SR0_PLLDIV ((*DANUBE_CGU_PLL_SR0 & (0xFFFFFFFF ^ ((1 << 28) - 1))) >> 28)
+#define CGU_PLL_SR0_PLLDEN (*DANUBE_CGU_PLL_SR0 & (1 << 26))
+#define CGU_PLL_SR0_PLLPSE GET_BITS(*DANUBE_CGU_PLL_SR0, 5, 4)
+#define CGU_PLL_SR0_PLLB (*DANUBE_CGU_PLL_SR0 & (1 << 2))
+#define CGU_PLL_SR0_PLLL (*DANUBE_CGU_PLL_SR0 & (1 << 1))
+#define CGU_PLL_SR0_PLLEN (*DANUBE_CGU_PLL_SR0 & (1 << 0))
+
+#define CGU_PLL_SR0_DSMSEL 1
+#define CGU_PLL_SR0_PHASE_DIV_EN 1
+
+/*
+ * CGU PLL1 NMK Register
+ */
+#define CGU_PLL_NMK1_PLLN ((*DANUBE_CGU_PLL_NMK1 & (0xFFFFFFFF ^ ((1 << 24) - 1))) >> 24)
+#define CGU_PLL_NMK1_PLLM GET_BITS(*DANUBE_CGU_PLL_NMK1, 23, 20)
+#define CGU_PLL_NMK1_PLLK GET_BITS(*DANUBE_CGU_PLL_NMK1, 19, 0)
+
+/*
+ * CGU PLL1 Status Register
+ */
+#define CGU_PLL_SR1_PLLDIV ((*DANUBE_CGU_PLL_SR1 & (0xFFFFFFFF ^ ((1 << 28) - 1))) >> 28)
+#define CGU_PLL_SR1_PLLDEN (*DANUBE_CGU_PLL_SR1 & (1 << 26))
+#define CGU_PLL_SR1_PLLPSE GET_BITS(*DANUBE_CGU_PLL_SR1, 5, 4)
+#define CGU_PLL_SR1_PLLB (*DANUBE_CGU_PLL_SR1 & (1 << 2))
+#define CGU_PLL_SR1_PLLL (*DANUBE_CGU_PLL_SR1 & (1 << 1))
+#define CGU_PLL_SR1_PLLEN (*DANUBE_CGU_PLL_SR1 & (1 << 0))
+
+#define CGU_PLL_SR1_DSMSEL 1
+#define CGU_PLL_SR1_PHASE_DIV_EN 1
+
+/*
+ * CGU PLL2 Status Register
+ */
+#define CGU_PLL_SR2_PLLDIV ((*DANUBE_CGU_PLL_SR2 & (0xFFFFFFFF ^ ((1 << 28) - 1))) >> 28)
+#define CGU_PLL_SR2_PLLDEN (*DANUBE_CGU_PLL_SR2 & (1 << 27))
+#define CGU_PLL_SR2_PLLN GET_BITS(*DANUBE_CGU_PLL_SR2, 25, 20)
+#define CGU_PLL_SR2_PLLM GET_BITS(*DANUBE_CGU_PLL_SR2, 19, 16)
+#define CGU_PLL_SR2_PLLPS (*DANUBE_CGU_PLL_SR2 & (1 << 5))
+#define CGU_PLL_SR2_PLLPE (*DANUBE_CGU_PLL_SR2 & (1 << 4))
+#define CGU_PLL_SR2_PLLB (*DANUBE_CGU_PLL_SR2 & (1 << 2))
+#define CGU_PLL_SR2_PLLL (*DANUBE_CGU_PLL_SR2 & (1 << 1))
+#define CGU_PLL_SR2_PLLEN (*DANUBE_CGU_PLL_SR2 & (1 << 0))
+
+/*
+ * CGU Interface Clock Register
+ */
+#define CGU_IF_CLK_CLKOD0 GET_BITS(*DANUBE_CGU_IF_CLK, 27, 26)
+#define CGU_IF_CLK_CLKOD1 GET_BITS(*DANUBE_CGU_IF_CLK, 25, 24)
+#define CGU_IF_CLK_CLKOD2 GET_BITS(*DANUBE_CGU_IF_CLK, 23, 22)
+#define CGU_IF_CLK_CLKOD3 GET_BITS(*DANUBE_CGU_IF_CLK, 21, 20)
+#define CGU_IF_CLK_PDA (*DANUBE_CGU_IF_CLK & (1 << 18))
+#define CGU_IF_CLK_PCI_B (*DANUBE_CGU_IF_CLK & (1 << 17))
+#define CGU_IF_CLK_PCIBM (*DANUBE_CGU_IF_CLK & (1 << 16))
+#define CGU_IF_CLK_MIICS (*DANUBE_CGU_IF_CLK & (1 << 3))
+#define CGU_IF_CLK_USBCS (*DANUBE_CGU_IF_CLK & (1 << 2))
+#define CGU_IF_CLK_PCIF (*DANUBE_CGU_IF_CLK & (1 << 1))
+#define CGU_IF_CLK_PCIS (*DANUBE_CGU_IF_CLK & (1 << 0))
+
+/*
+ * CGU Oscillator Control Register
+ */
+#define CGU_OSC_CTRL GET_BITS(*DANUBE_CGU_OSC_CTRL, 1, 0)
+
+/*
+ * CGU SDRAM Memory Delay Register
+ */
+#define CGU_SMD_CLKI (*DANUBE_CGU_SMD & (1 << 31))
+#define CGU_SMD_MIDS GET_BITS(*DANUBE_CGU_SMD, 17, 12)
+#define CGU_SMD_MODS GET_BITS(*DANUBE_CGU_SMD, 11, 6)
+#define CGU_SMD_MDSEL GET_BITS(*DANUBE_CGU_SMD, 5, 0)
+
+/*
+ * CGU CPU Clock Reduction Register
+ */
+#define CGU_CRD_SFTR (*DANUBE_CGU_CRD & (1 << 31))
+#define CGU_CRD_DIVE (*DANUBE_CGU_CRD & (1 << 16))
+#define CGU_CRD_CRD1 GET_BITS(*DANUBE_CGU_CRD, 3, 2)
+#define CGU_CRD_CRD GET_BITS(*DANUBE_CGU_CRD, 1, 0)
+
+/*
+ * CGU CT Status Register 1
+ */
+#define CGU_CT1SR_PDOUT GET_BITS(*DANUBE_CGU_CT1SR, 13, 0)
+
+/*
+ * CGU CT Status Register 2
+ */
+#define CGU_CT2SR_PLL1K GET_BITS(*DANUBE_CGU_CT2SR, 9, 0)
+
+/*
+ * CGU PCM Control Register
+ */
+#define CGU_PCMCR_DCL1 GET_BITS(*DANUBE_CGU_PCMCR, 27, 25)
+#define CGU_PCMCR_MUXDCL (*DANUBE_CGU_PCMCR & (1 << 22))
+#define CGU_PCMCR_MUXFSC (*DANUBE_CGU_PCMCR & (1 << 18))
+#define CGU_PCMCR_PCM_SL (*DANUBE_CGU_PCMCR & (1 << 13))
+#define CGU_PCMCR_DNTR (*DANUBE_CGU_PCMCR & (1 << 12))
+
+/*
+ * CGU Clock Mux Register
+ */
+#define CGU_MUX_MII_CLK (*DANUBE_CGU_MUX & (1 << 6))
+#define CGU_MUX_SUB_SYS GET_BITS(*DANUBE_CGU_MUX, 5, 3)
+#define CGU_MUX_PP32 GET_BITS(*DANUBE_CGU_MUX, 1, 0)
+
+
+/*
+ * ####################################
+ * Preparation of Debug on Amazon Chip
+ * ####################################
+ */
+
+/*
+ * If try module on Amazon chip, prepare some tricks to prevent invalid memory write.
+ */
+#if defined(DEBUG_ON_AMAZON) && DEBUG_ON_AMAZON
+ u32 g_pFakeRegisters[0x0100];
+
+ #undef DANUBE_CGU
+ #define DANUBE_CGU ((u32)g_pFakeRegisters)
+#endif // defined(DEBUG_ON_AMAZON) && DEBUG_ON_AMAZON
+
+
+/*
+ * ####################################
+ * Data Type
+ * ####################################
+ */
+
+
+/*
+ * ####################################
+ * Declaration
+ * ####################################
+ */
+
+/*
+ * Pre-declaration of File Operations
+ */
+static ssize_t cgu_read(struct file *, char *, size_t, loff_t *);
+static ssize_t cgu_write(struct file *, const char *, size_t, loff_t *);
+static int cgu_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
+static int cgu_open(struct inode *, struct file *);
+static int cgu_release(struct inode *, struct file *);
+
+/*
+ * Pre-declaration of 64-bit Unsigned Integer Operation
+ */
+static inline void uint64_multiply(unsigned int, unsigned int, unsigned int *);
+static inline void uint64_divide(unsigned int *, unsigned int, unsigned int *, unsigned int *);
+
+/*
+ * Calculate PLL Frequency
+ */
+static inline u32 cal_dsm(u32, u32);
+static inline u32 mash_dsm(u32, u32, u32);
+static inline u32 ssff_dsm_1(u32, u32, u32);
+static inline u32 ssff_dsm_2(u32, u32, u32);
+static inline u32 dsm(u32 M, u32, u32, int, int);
+static inline u32 cgu_get_pll0_fosc(void);
+static inline u32 cgu_get_pll0_fps(void);
+static inline u32 cgu_get_pll0_fdiv(void);
+static inline u32 cgu_get_pll1_fosc(void);
+static inline u32 cgu_get_pll1_fps(void);
+static inline u32 cgu_get_pll1_fdiv(void);
+static inline u32 cgu_get_pll2_fosc(void);
+static inline u32 cgu_get_pll2_fps(void);
+
+/*
+ * Export Functions
+ */
+u32 cgu_get_mips_clock(int);
+u32 cgu_get_cpu_clock(void);
+u32 cgu_get_io_region_clock(void);
+u32 cgu_get_fpi_bus_clock(int);
+u32 cgu_get_pp32_clock(void);
+u32 cgu_get_pci_clock(void);
+u32 cgu_get_ethernet_clock(void);
+u32 cgu_get_usb_clock(void);
+u32 cgu_get_clockout(int);
+
+
+/*
+ * ####################################
+ * Local Variable
+ * ####################################
+ */
+
+static struct file_operations cgu_fops = {
+ owner: THIS_MODULE,
+ llseek: no_llseek,
+ read: cgu_read,
+ write: cgu_write,
+ ioctl: cgu_ioctl,
+ open: cgu_open,
+ release: cgu_release
+};
+
+static struct miscdevice cgu_miscdev = {
+ MISC_DYNAMIC_MINOR,
+ "danube_cgu_dev",
+ &cgu_fops
+};
+
+
+/*
+ * ####################################
+ * Global Variable
+ * ####################################
+ */
+
+
+/*
+ * ####################################
+ * Local Function
+ * ####################################
+ */
+
+static ssize_t cgu_read(struct file *file, char *buf, size_t count, loff_t *ppos)
+{
+ return -EPERM;
+}
+
+static ssize_t cgu_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
+{
+ return -EPERM;
+}
+
+static int cgu_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+ int ret = 0;
+ struct cgu_clock_rates rates;
+
+ if ( _IOC_TYPE(cmd) != CGU_IOC_MAGIC
+ || _IOC_NR(cmd) >= CGU_IOC_MAXNR )
+ return -ENOTTY;
+
+ if ( _IOC_DIR(cmd) & _IOC_READ )
+ ret = !access_ok(VERIFY_WRITE, arg, _IOC_SIZE(cmd));
+ else if ( _IOC_DIR(cmd) & _IOC_WRITE )
+ ret = !access_ok(VERIFY_READ, arg, _IOC_SIZE(cmd));
+ if ( ret )
+ return -EFAULT;
+
+ switch ( cmd )
+ {
+ case CGU_GET_CLOCK_RATES:
+ /* Calculate Clock Rates */
+ rates.mips0 = cgu_get_mips_clock(0);
+ rates.mips1 = cgu_get_mips_clock(1);
+ rates.cpu = cgu_get_cpu_clock();
+ rates.io_region = cgu_get_io_region_clock();
+ rates.fpi_bus1 = cgu_get_fpi_bus_clock(1);
+ rates.fpi_bus2 = cgu_get_fpi_bus_clock(2);
+ rates.pp32 = cgu_get_pp32_clock();
+ rates.pci = cgu_get_pci_clock();
+ rates.ethernet = cgu_get_ethernet_clock();
+ rates.usb = cgu_get_usb_clock();
+ rates.clockout0 = cgu_get_clockout(0);
+ rates.clockout1 = cgu_get_clockout(1);
+ rates.clockout2 = cgu_get_clockout(2);
+ rates.clockout3 = cgu_get_clockout(3);
+ /* Copy to User Space */
+ copy_to_user((char*)arg, (char*)&rates, sizeof(rates));
+
+ ret = 0;
+ break;
+ default:
+ ret = -ENOTTY;
+ }
+
+ return ret;
+}
+
+static int cgu_open(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static int cgu_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+/*
+ * Description:
+ * calculate 64-bit multiplication result of two 32-bit unsigned integer
+ * Input:
+ * u32Multiplier1 --- u32 (32-bit), one of the multipliers
+ * u32Multiplier2 --- u32 (32-bit), the other multiplier
+ * u32Result --- u32[2], array to retrieve the multiplication result,
+ * index 0 is high word, index 1 is low word
+ * Output:
+* none
+ */
+static inline void uint64_multiply(u32 u32Multiplier1, u32 u32Multiplier2, u32 u32Result[2])
+{
+ u32 u32Multiplier1LowWord = u32Multiplier1 & 0xFFFF;
+ u32 u32Multiplier1HighWord = u32Multiplier1 >> 16;
+ u32 u32Multiplier2LowWord = u32Multiplier2 & 0xFFFF;
+ u32 u32Multiplier2HighWord = u32Multiplier2 >> 16;
+ u32 u32Combo1, u32Combo2, u32Combo3, u32Combo4;
+ u32 u32Word1, u32Word2, u32Word3, u32Word4;
+
+ u32Combo1 = u32Multiplier1LowWord * u32Multiplier2LowWord;
+ u32Combo2 = u32Multiplier1HighWord * u32Multiplier2LowWord;
+ u32Combo3 = u32Multiplier1LowWord * u32Multiplier2HighWord;
+ u32Combo4 = u32Multiplier1HighWord * u32Multiplier2HighWord;
+
+ u32Word1 = u32Combo1 & 0xFFFF;
+ u32Word2 = (u32Combo1 >> 16) + (u32Combo2 & 0xFFFF) + (u32Combo3 & 0xFFFF);
+ u32Word3 = (u32Combo2 >> 16) + (u32Combo3 >> 16) + (u32Combo4 & 0xFFFF) + (u32Word2 >> 16);
+ u32Word4 = (u32Combo4 >> 16) + (u32Word3 >> 16);
+
+ u32Result[0] = (u32Word4 << 16) | u32Word3;
+ u32Result[1] = (u32Word2 << 16) | u32Word1;
+}
+
+/*
+ * Description:
+ * divide 64-bit unsigned integer with 32-bit unsigned integer
+ * Input:
+ * u32Numerator --- u32[2], index 0 is high word of numerator, while
+ * index 1 is low word of numerator
+ * u32Denominator --- u32 (32-bit), the denominator in division, this
+ * parameter can not be zero, or lead to unpredictable
+ * result
+ * pu32Quotient --- u32 *, the pointer to retrieve 32-bit quotient, null
+ * pointer means ignore quotient
+ * pu32Residue --- u32 *, the pointer to retrieve 32-bit residue null
+ * pointer means ignore residue
+ * Output:
+ * none
+ */
+static inline void uint64_divide(u32 u32Numerator[2], u32 u32Denominator, u32 *pu32Quotient, u32 *pu32Residue)
+{
+ u32 u32DWord1, u32DWord2, u32DWord3;
+ u32 u32Quotient;
+ int i;
+
+ u32DWord3 = 0;
+ u32DWord2 = u32Numerator[0];
+ u32DWord1 = u32Numerator[1];
+
+ u32Quotient = 0;
+
+ for ( i = 0; i < 64; i++ )
+ {
+ u32DWord3 = (u32DWord3 << 1) | (u32DWord2 >> 31);
+ u32DWord2 = (u32DWord2 << 1) | (u32DWord1 >> 31);
+ u32DWord1 <<= 1;
+ u32Quotient <<= 1;
+ if ( u32DWord3 >= u32Denominator )
+ {
+ u32DWord3 -= u32Denominator;
+ u32Quotient |= 1;
+ }
+ }
+ if ( pu32Quotient )
+ *pu32Quotient = u32Quotient;
+ if ( pu32Residue )
+ *pu32Residue = u32DWord3;
+}
+
+/*
+ * Description:
+ * common routine to calculate PLL frequency
+ * Input:
+ * num --- u32, numerator
+ * den --- u32, denominator
+ * Output:
+ * u32 --- frequency the PLL output
+ */
+static inline u32 cal_dsm(u32 num, u32 den)
+{
+ u32 ret;
+ u32 temp[2];
+ u32 residue;
+
+ uint64_multiply(num, BASIC_INPUT_CLOCK_FREQUENCY, temp);
+ uint64_divide(temp, den, &ret, &residue);
+ if ( (residue << 1) >= den )
+ ret++;
+
+ return ret;
+}
+
+/*
+ * Description:
+ * calculate PLL frequency following MASH-DSM
+ * Input:
+ * M --- u32, denominator coefficient
+ * N --- u32, numerator integer coefficient
+ * K --- u32, numerator fraction coefficient
+ * Output:
+ * u32 --- frequency the PLL output
+ */
+static inline u32 mash_dsm(u32 M, u32 N, u32 K)
+{
+ u32 num = ((N + 1) << 10) + K;
+ u32 den = (M + 1) << 10;
+
+ return cal_dsm(num, den);
+}
+
+/*
+ * Description:
+ * calculate PLL frequency following SSFF-DSM (0.25 < fraction < 0.75)
+ * Input:
+ * M --- u32, denominator coefficient
+ * N --- u32, numerator integer coefficient
+ * K --- u32, numerator fraction coefficient
+ * Output:
+ * u32 --- frequency the PLL output
+ */
+static inline u32 ssff_dsm_1(u32 M, u32 N, u32 K)
+{
+ u32 num = ((N + 1) << 11) + K + 512;
+ u32 den = (M + 1) << 11;
+
+ return cal_dsm(num, den);
+}
+
+/*
+ * Description:
+ * calculate PLL frequency following SSFF-DSM
+ * (fraction < 0.125 || fraction > 0.875)
+ * Input:
+ * M --- u32, denominator coefficient
+ * N --- u32, numerator integer coefficient
+ * K --- u32, numerator fraction coefficient
+ * Output:
+ * u32 --- frequency the PLL output
+ */
+static inline u32 ssff_dsm_2(u32 M, u32 N, u32 K)
+{
+ u32 num = K >= 512 ? ((N + 1) << 12) + K - 512 : ((N + 1) << 12) + K + 3584;
+ u32 den = (M + 1) << 12;
+
+ return cal_dsm(num, den);
+}
+
+/*
+ * Description:
+ * calculate PLL frequency
+ * Input:
+ * M --- u32, denominator coefficient
+ * N --- u32, numerator integer coefficient
+ * K --- u32, numerator fraction coefficient
+ * dsmsel --- int, 0: MASH-DSM, 1: SSFF-DSM
+ * phase_div_en --- int, 0: 0.25 < fraction < 0.75
+ * 1: fraction < 0.125 || fraction > 0.875
+ * Output:
+ * u32 --- frequency the PLL output
+ */
+static inline u32 dsm(u32 M, u32 N, u32 K, int dsmsel, int phase_div_en)
+{
+ if ( !dsmsel )
+ return mash_dsm(M, N, K);
+ else
+ if ( !phase_div_en )
+ return ssff_dsm_1(M, N, K);
+ else
+ return ssff_dsm_2(M, N, K);
+}
+
+/*
+ * Description:
+ * get oscillate frequency of PLL0
+ * Input:
+ * none
+ * Output:
+ * u32 --- frequency of PLL0 Fosc
+ */
+static inline u32 cgu_get_pll0_fosc(void)
+{
+ return CGU_PLL_SR0_PLLB ? BASIC_INPUT_CLOCK_FREQUENCY : dsm(CGU_PLL_NMK0_PLLM, CGU_PLL_NMK0_PLLN, CGU_PLL_NMK0_PLLK, CGU_PLL_SR0_DSMSEL, CGU_PLL_SR0_PHASE_DIV_EN);
+}
+
+/*
+ * Description:
+ * get output frequency of PLL0 phase shifter
+ * Input:
+ * none
+ * Output:
+ * u32 --- frequency of PLL0 Fps
+ */
+static inline u32 cgu_get_pll0_fps(void)
+{
+ register u32 fps = cgu_get_pll0_fosc();
+
+ switch ( CGU_PLL_SR0_PLLPSE )
+ {
+ case 1:
+ /* 1.5 */
+ fps = ((fps << 1) + 1) / 3; break;
+ case 2:
+ /* 1.25 */
+ fps = ((fps << 2) + 2) / 5; break;
+ case 3:
+ /* 3.5 */
+ fps = ((fps << 1) + 3) / 7;
+ }
+ return fps;
+}
+
+/*
+ * Description:
+ * get output frequency of PLL0 output divider
+ * Input:
+ * none
+ * Output:
+ * u32 --- frequency of PLL0 Fdiv
+ */
+static inline u32 cgu_get_pll0_fdiv(void)
+{
+ register u32 fdiv = cgu_get_pll0_fosc();
+
+ if ( CGU_PLL_SR0_PLLDEN )
+ fdiv = (fdiv + (CGU_PLL_SR0_PLLDIV + 1) / 2) / (CGU_PLL_SR0_PLLDIV + 1);
+ return fdiv;
+}
+
+/*
+ * Description:
+ * get oscillate frequency of PLL1
+ * Input:
+ * none
+ * Output:
+ * u32 --- frequency of PLL1 Fosc
+ */
+static inline u32 cgu_get_pll1_fosc(void)
+{
+ return CGU_PLL_SR1_PLLB ? BASIC_INPUT_CLOCK_FREQUENCY : dsm(CGU_PLL_NMK1_PLLM, CGU_PLL_NMK1_PLLN, CGU_PLL_NMK1_PLLK, CGU_PLL_SR1_DSMSEL, CGU_PLL_SR1_PHASE_DIV_EN);
+}
+
+/*
+ * Description:
+ * get output frequency of PLL1 phase shifter
+ * Input:
+ * none
+ * Output:
+ * u32 --- frequency of PLL1 Fps
+ */
+static inline u32 cgu_get_pll1_fps(void)
+{
+ register u32 fps = cgu_get_pll1_fosc();
+
+ switch ( CGU_PLL_SR1_PLLPSE )
+ {
+ case 1:
+ /* 1.5 */
+ fps = ((fps << 1) + 1) / 3; break;
+ case 2:
+ /* 1.25 */
+ fps = ((fps << 2) + 2) / 5; break;
+ case 3:
+ /* 3.5 */
+ fps = ((fps << 1) + 3) / 7;
+ }
+ return fps;
+}
+
+/*
+ * Description:
+ * get output frequency of PLL1 output divider
+ * Input:
+ * none
+ * Output:
+ * u32 --- frequency of PLL1 Fdiv
+ */
+static inline u32 cgu_get_pll1_fdiv(void)
+{
+ register u32 fdiv = cgu_get_pll1_fosc();
+
+ if ( CGU_PLL_SR1_PLLDEN )
+ fdiv = (fdiv + (CGU_PLL_SR1_PLLDIV + 1) / 2) / (CGU_PLL_SR1_PLLDIV + 1);
+ return fdiv;
+}
+
+/*
+ * Description:
+ * get oscillate frequency of PLL2
+ * Input:
+ * none
+ * Output:
+ * u32 --- frequency of PLL2 Fosc
+ */
+static inline u32 cgu_get_pll2_fosc(void)
+{
+ u32 ret;
+ u32 temp[2];
+ u32 residue;
+
+ uint64_multiply((CGU_PLL_SR2_PLLN + 1) * 8, cgu_get_pll0_fdiv(), temp);
+ uint64_divide(temp, CGU_PLL_SR2_PLLM + 1, &ret, &residue);
+ if ( (residue << 1) >= CGU_PLL_SR2_PLLM )
+ ret++;
+
+ return ret;
+}
+
+/*
+ * Description:
+ * get output frequency of PLL2 phase shifter
+ * Input:
+ * none
+ * Output:
+ * u32 --- frequency of PLL2 Fps
+ */
+static inline u32 cgu_get_pll2_fps(void)
+{
+ register u32 fps = cgu_get_pll2_fosc();
+
+ if ( CGU_PLL_SR2_PLLPE )
+ {
+ if ( CGU_PLL_SR2_PLLPS )
+ /* 1.25 */
+ fps = ((fps << 3) + 4) / 9;
+ else
+ /* 1.125 */
+ fps = ((fps << 2) + 2) / 5;
+ }
+
+ return fps;
+}
+
+
+/*
+ * ####################################
+ * Global Function
+ * ####################################
+ */
+
+/*
+ * Description:
+ * get frequency of MIPS (0: core, 1: DSP)
+ * Input:
+ * cpu --- int, 0: core, 1: DSP
+ * Output:
+ * u32 --- frequency of MIPS coprocessor (0: core, 1: DSP)
+ */
+u32 cgu_get_mips_clock(int cpu)
+{
+ register u32 ret = cgu_get_pll0_fosc();
+
+ if ( CGU_CRD_CRD )
+ ret = (ret + (CGU_CRD_CRD >> 1)) / (CGU_CRD_CRD + 1);
+ if ( cpu == 0 && CGU_CRD_CRD1 )
+ ret >>= CGU_CRD_CRD1;
+ return ret;
+}
+
+/*
+ * Description:
+ * get frequency of MIPS core
+ * Input:
+ * none
+ * Output:
+ * u32 --- frequency of MIPS core
+ */
+u32 cgu_get_cpu_clock(void)
+{
+ return cgu_get_mips_clock(0);
+}
+
+/*
+ * Description:
+ * get frequency of sub-system and memory controller
+ * Input:
+ * none
+ * Output:
+ * u32 --- frequency of sub-system and memory controller
+ */
+u32 cgu_get_io_region_clock(void)
+{
+ register u32 ret = (CGU_MUX_SUB_SYS > 4) ? cgu_get_pll0_fosc() : cgu_get_mips_clock(1);
+
+ switch ( CGU_MUX_SUB_SYS )
+ {
+ case 0:
+ break;
+ case 1:
+ default:
+ ret = (ret + 1) >> 1; break;
+ case 2:
+ ret = (ret + 1) / 3; break;
+ case 3:
+ ret = (ret + 2) >> 2; break;
+ case 5:
+ ret = ((ret << 1) + 1) / 3; break;
+ case 6:
+ ret = ((ret << 1) + 2) / 5;
+ }
+
+ return ret;
+}
+
+/*
+ * Description:
+ * get frequency of FPI bus
+ * Input:
+ * fpi --- int, 1: FPI bus 1 (FBS1/Fast FPI Bus), 2: FPI bus 2 (FBS2)
+ * Output:
+ * u32 --- frequency of FPI bus
+ */
+u32 cgu_get_fpi_bus_clock(int fpi)
+{
+ register u32 ret = cgu_get_io_region_clock();
+
+ if ( fpi == 2 )
+ ret >>= 1;
+ return ret;
+}
+
+/*
+ * Description:
+ * get frequency of PP32 processor
+ * Input:
+ * none
+ * Output:
+ * u32 --- frequency of PP32 processor
+ */
+u32 cgu_get_pp32_clock(void)
+{
+ register u32 ret;
+
+ switch ( CGU_MUX_PP32 )
+ {
+ case 0:
+ default:
+ ret = ((cgu_get_pll2_fosc() << 2) + 2) / 5; break;
+ case 1:
+ ret = ((cgu_get_pll2_fosc() << 3) + 4) / 9; break;
+ case 2:
+ ret = cgu_get_fpi_bus_clock(1); break;
+ case 3:
+ ret = cgu_get_mips_clock(1);
+ }
+
+ return ret;
+}
+
+/*
+ * Description:
+ * get frequency of PCI bus
+ * Input:
+ * none
+ * Output:
+ * u32 --- frequency of PCI bus
+ */
+u32 cgu_get_pci_clock(void)
+{
+ register u32 ret = 0;
+
+ if ( !CGU_IF_CLK_PCIS )
+ {
+ ret = cgu_get_pll2_fosc();
+ if ( CGU_IF_CLK_PCIF )
+ ret = (ret + 2) / 5;
+ else
+ ret = (ret + 4) / 9;
+ }
+
+ return ret;
+}
+
+/*
+ * Description:
+ * get frequency of ethernet module (MII)
+ * Input:
+ * none
+ * Output:
+ * u32 --- frequency of ethernet module
+ */
+u32 cgu_get_ethernet_clock(void)
+{
+ register u32 ret = 0;
+
+ if ( !CGU_IF_CLK_MIICS )
+ {
+ ret = cgu_get_pll2_fosc();
+ if ( CGU_MUX_MII_CLK )
+ ret = (ret + 3) / 6;
+ else
+ ret = (ret + 6) / 12;
+ }
+
+ return ret;
+}
+
+/*
+ * Description:
+ * get frequency of USB
+ * Input:
+ * none
+ * Output:
+ * u32 --- frequency of USB
+ */
+u32 cgu_get_usb_clock(void)
+{
+ return CGU_IF_CLK_USBCS ? 12000000 : (cgu_get_pll2_fosc() + 12) / 25;
+}
+
+/*
+ * Description:
+ * get frequency of CLK_OUT pin
+ * Input:
+ * clkout --- int, clock out pin number
+ * Output:
+ * u32 --- frequency of CLK_OUT pin
+ */
+u32 cgu_get_clockout(int clkout)
+{
+ u32 fosc1 = cgu_get_pll1_fosc();
+ u32 fosc2 = cgu_get_pll2_fosc();
+
+ if ( clkout > 3 || clkout < 0 )
+ return 0;
+
+ switch ( ((u32)clkout << 2) | GET_BITS(*DANUBE_CGU_IF_CLK, 21 + clkout * 2, 20 + clkout * 2) )
+ {
+ case 0: /* 32.768KHz */
+ case 14:
+ return (fosc1 + 6000) / 12000;
+ case 1: /* 1.536MHz */
+ return (fosc1 + 128) / 256;
+ case 2: /* 2.5MHz */
+ return (fosc2 + 60) / 120;
+ case 3: /* 12MHz */
+ case 5:
+ case 12:
+ return (fosc2 + 12) / 25;
+ case 4: /* 40MHz */
+ return (fosc2 * 2 + 7) / 15;
+ case 6: /* 24MHz */
+ return (fosc2 * 2 + 12) / 25;
+ case 7: /* 48MHz */
+ return (fosc2 * 4 + 12) / 25;
+ case 8: /* 25MHz */
+ case 15:
+ return (fosc2 + 6) / 12;
+ case 9: /* 50MHz */
+ case 13:
+ return (fosc2 + 3) / 6;
+ case 10:/* 30MHz */
+ return (fosc2 + 5) / 10;
+ case 11:/* 60MHz */
+ return (fosc2 + 2) / 5;
+ }
+
+ return 0;
+}
+
+
+/*
+ * ####################################
+ * Init/Cleanup API
+ * ####################################
+ */
+
+/*
+ * Description:
+ * register device
+ * Input:
+ * none
+ * Output:
+ * 0 --- successful
+ * else --- failure, usually it is negative value of error code
+ */
+int __init danube_cgu_init(void)
+{
+ int ret;
+
+ ret = misc_register(&cgu_miscdev);
+ if ( ret )
+ {
+ printk(KERN_ERR "cgu: can't misc_register\n");
+ return ret;
+ }
+ else
+ printk(KERN_INFO "cgu: misc_register on minor = %d\n", cgu_miscdev.minor);
+
+ /*
+ * initialize fake registers to do testing on Amazon
+ */
+#if defined(DEBUG_ON_AMAZON) && DEBUG_ON_AMAZON
+ #ifdef DEBUG_PRINT_INFO
+ #undef DEBUG_PRINT_INFO
+ #endif
+ #define DEBUG_PRINT_INFO 1
+
+ *DANUBE_CGU_DIV = 0x00010019;
+ *DANUBE_CGU_PLL_NMK0 = 0x416002C3;
+ *DANUBE_CGU_PLL_SR0 = 0x74000013;
+ *DANUBE_CGU_PLL_NMK1 = 0x4C60009C;
+ *DANUBE_CGU_PLL_SR1 = 0x54000013;
+ *DANUBE_CGU_PLL_SR2 = 0x58890013;
+ *DANUBE_CGU_IF_CLK = 0x00000000;
+ *DANUBE_CGU_OSC_CTRL = 0x00000000;
+ *DANUBE_CGU_SMD = 0x00000000;
+ *DANUBE_CGU_CRD = 0x00010000;
+ *DANUBE_CGU_CT1SR = 0x00000000;
+ *DANUBE_CGU_CT2SR = CGU_PLL_NMK1_PLLK;
+ *DANUBE_CGU_PCMCR = 0x00000000;
+ *DANUBE_CGU_MUX = 0x00000008;
+#endif // defined(DEBUG_ON_AMAZON) && DEBUG_ON_AMAZON
+
+ /*
+ * for testing only
+ */
+#if defined(DEBUG_PRINT_INFO) && DEBUG_PRINT_INFO
+ printk("pll0 N = %d, M = %d, K = %d, DIV = %d\n", CGU_PLL_NMK0_PLLN, CGU_PLL_NMK0_PLLM, CGU_PLL_NMK0_PLLK, CGU_PLL_SR0_PLLDIV);
+ printk("pll1 N = %d, M = %d, K = %d, DIV = %d\n", CGU_PLL_NMK1_PLLN, CGU_PLL_NMK1_PLLM, CGU_PLL_NMK1_PLLK, CGU_PLL_SR1_PLLDIV);
+ printk("pll2 N = %d, M = %d, DIV = %d\n", CGU_PLL_SR2_PLLN, CGU_PLL_SR2_PLLM, CGU_PLL_SR2_PLLDIV);
+ printk("pll0_fosc = %d\n", cgu_get_pll0_fosc());
+ printk("pll0_fps = %d\n", cgu_get_pll0_fps());
+ printk("pll0_fdiv = %d\n", cgu_get_pll0_fdiv());
+ printk("pll1_fosc = %d\n", cgu_get_pll1_fosc());
+ printk("pll1_fps = %d\n", cgu_get_pll1_fps());
+ printk("pll1_fdiv = %d\n", cgu_get_pll1_fdiv());
+ printk("pll2_fosc = %d\n", cgu_get_pll2_fosc());
+ printk("pll2_fps = %d\n", cgu_get_pll2_fps());
+ printk("mips0 clock = %d\n", cgu_get_mips_clock(0));
+ printk("mips1 clock = %d\n", cgu_get_mips_clock(1));
+ printk("cpu clock = %d\n", cgu_get_cpu_clock());
+ printk("IO region = %d\n", cgu_get_io_region_clock());
+ printk("FPI bus 1 = %d\n", cgu_get_fpi_bus_clock(1));
+ printk("FPI bus 2 = %d\n", cgu_get_fpi_bus_clock(2));
+ printk("PP32 clock = %d\n", cgu_get_pp32_clock());
+ printk("PCI clock = %d\n", cgu_get_pci_clock());
+ printk("Ethernet = %d\n", cgu_get_ethernet_clock());
+ printk("USB clock = %d\n", cgu_get_usb_clock());
+ printk("Clockout0 = %d\n", cgu_get_clockout(0));
+ printk("Clockout1 = %d\n", cgu_get_clockout(1));
+ printk("Clockout2 = %d\n", cgu_get_clockout(2));
+ printk("Clockout3 = %d\n", cgu_get_clockout(3));
+#endif // defined(DEBUG_PRINT_INFO) && DEBUG_PRINT_INFO
+
+ return 0;
+}
+
+/*
+ * Description:
+ * deregister device
+ * Input:
+ * none
+ * Output:
+ * none
+ */
+void __exit danube_cgu_exit(void)
+{
+ int ret;
+
+ ret = misc_deregister(&cgu_miscdev);
+ if ( ret )
+ printk(KERN_ERR "cgu: can't misc_deregister, get error number %d\n", -ret);
+ else
+ printk(KERN_INFO "cgu: misc_deregister successfully\n");
+}
+
+module_init(danube_cgu_init);
+module_exit(danube_cgu_exit);
diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/ifx_cgu.h b/package/uboot-ifxmips/files/cpu/mips/danube/ifx_cgu.h
new file mode 100644
index 000000000..78fe21d62
--- /dev/null
+++ b/package/uboot-ifxmips/files/cpu/mips/danube/ifx_cgu.h
@@ -0,0 +1,91 @@
+#ifndef __DANUBE_CGU_DEV_H__2005_07_20__14_26__
+#define __DANUBE_CGU_DEV_H__2005_07_20__14_26__
+
+
+/******************************************************************************
+ Copyright (c) 2002, Infineon Technologies. All rights reserved.
+
+ No Warranty
+ Because the program is licensed free of charge, there is no warranty for
+ the program, to the extent permitted by applicable law. Except when
+ otherwise stated in writing the copyright holders and/or other parties
+ provide the program "as is" without warranty of any kind, either
+ expressed or implied, including, but not limited to, the implied
+ warranties of merchantability and fitness for a particular purpose. The
+ entire risk as to the quality and performance of the program is with
+ you. should the program prove defective, you assume the cost of all
+ necessary servicing, repair or correction.
+
+ In no event unless required by applicable law or agreed to in writing
+ will any copyright holder, or any other party who may modify and/or
+ redistribute the program as permitted above, be liable to you for
+ damages, including any general, special, incidental or consequential
+ damages arising out of the use or inability to use the program
+ (including but not limited to loss of data or data being rendered
+ inaccurate or losses sustained by you or third parties or a failure of
+ the program to operate with any other programs), even if such holder or
+ other party has been advised of the possibility of such damages.
+******************************************************************************/
+
+
+/*
+ * ####################################
+ * Definition
+ * ####################################
+ */
+
+/*
+ * ioctl Command
+ */
+#define CGU_IOC_MAGIC 'u'
+#define CGU_GET_CLOCK_RATES _IOW(CGU_IOC_MAGIC, 0, struct cgu_clock_rates)
+#define CGU_IOC_MAXNR 1
+
+
+/*
+ * ####################################
+ * Data Type
+ * ####################################
+ */
+
+/*
+ * Data Type Used to Call ioctl(GET_CLOCK_RATES)
+ */
+struct cgu_clock_rates {
+ u32 mips0;
+ u32 mips1;
+ u32 cpu;
+ u32 io_region;
+ u32 fpi_bus1;
+ u32 fpi_bus2;
+ u32 pp32;
+ u32 pci;
+ u32 ethernet;
+ u32 usb;
+ u32 clockout0;
+ u32 clockout1;
+ u32 clockout2;
+ u32 clockout3;
+};
+
+
+/*
+ * ####################################
+ * Declaration
+ * ####################################
+ */
+
+#if defined(__KERNEL__)
+ extern u32 cgu_get_mips_clock(int);
+ extern u32 cgu_get_cpu_clock(void);
+ extern u32 cgu_get_io_region_clock(void);
+ extern u32 cgu_get_fpi_bus_clock(int);
+ extern u32 cgu_get_pp32_clock(void);
+ extern u32 cgu_get_pci_clock(void);
+ extern u32 cgu_get_ethernet_clock(void);
+ extern u32 cgu_get_usb_clock(void);
+ extern u32 cgu_get_clockout(int);
+#endif // defined(__KERNEL__)
+
+
+#endif // __DANUBE_CGU_DEV_H__2005_07_20__14_26__
diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/ifx_clock.c b/package/uboot-ifxmips/files/cpu/mips/danube/ifx_clock.c
new file mode 100644
index 000000000..0a1cdacdc
--- /dev/null
+++ b/package/uboot-ifxmips/files/cpu/mips/danube/ifx_clock.c
@@ -0,0 +1,91 @@
+/*
+ * (C) Copyright 2003
+ * 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 <common.h>
+#include <asm-mips/danube.h>
+
+
+
+/*******************************************************************************
+*
+* get_cpuclk - returns the frequency of the CPU.
+*
+* NOTE:
+* This functions should be used by the hardware driver to get the correct
+* frequency of the CPU.
+*/
+
+unsigned int danube_get_ddr_hz(void)
+{
+ switch((*DANUBE_CGU_SYS) & 0x3){
+ case 0:
+ return 166666667;
+ case 1:
+ return 133333333;
+ case 2:
+ return 111111111;
+ case 3:
+ return 83333333;
+ }
+}
+
+
+uint danube_get_cpuclk(void)
+{
+#ifdef CONFIG_USE_EMULATOR
+ return EMULATOR_CPU_SPEED;
+#else //NOT CONFIG_USE_EMULATOR
+ unsigned int ddr_clock=danube_get_ddr_hz();
+ switch((*DANUBE_CGU_SYS) & 0xc){
+ case 0:
+ return 333333333;
+ case 4:
+ return ddr_clock;
+ case 8:
+ return ddr_clock << 1;
+ default:
+ break;
+ /*reserved*/
+ }
+#endif
+
+}
+
+
+uint danube_get_fpiclk(void)
+{
+#ifdef CONFIG_USE_EMULATOR
+ unsigned int clkCPU;
+ clkCPU = danube_get_cpu_hz();
+ return clkCPU >> 2;
+#else //NOT CONFIG_USE_EMULATOR
+ unsigned int ddr_clock=danube_get_ddr_hz();
+ if ((*DANUBE_CGU_SYS) & 0x40){
+ return ddr_clock >> 1;
+ }
+ return ddr_clock;
+#endif
+
+}
+
+
diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/ifx_cpu.c b/package/uboot-ifxmips/files/cpu/mips/danube/ifx_cpu.c
new file mode 100644
index 000000000..49355de55
--- /dev/null
+++ b/package/uboot-ifxmips/files/cpu/mips/danube/ifx_cpu.c
@@ -0,0 +1,5 @@
+
+#define IFX_CPU_RESET \
+{ *DANUBE_RCU_RST_REQ |=1<<30; \
+}
+
diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/ifx_start.S b/package/uboot-ifxmips/files/cpu/mips/danube/ifx_start.S
new file mode 100644
index 000000000..17c0b0ae5
--- /dev/null
+++ b/package/uboot-ifxmips/files/cpu/mips/danube/ifx_start.S
@@ -0,0 +1,51 @@
+/*
+ * IFX Platform Dependent CPU Initializations
+ * - for Danube
+ */
+
+#define IFX_EBU_BOOTCFG_DWORD \
+ .word INFINEON_EBU_BOOTCFG; /* EBU init code, fetched during booting */ \
+ .word 0x00000000; /* phases of the flash */
+
+#define IFX_MORE_RESERVED_VECTORS \
+ XVECENT(romExcHandle,0x400); /* Int, CauseIV=1 */ \
+ RVECENT(romReserved,129); \
+ RVECENT(romReserved,130); \
+ RVECENT(romReserved,131); \
+ RVECENT(romReserved,132); \
+ RVECENT(romReserved,133); \
+ RVECENT(romReserved,134); \
+ RVECENT(romReserved,135); \
+ RVECENT(romReserved,136); \
+ RVECENT(romReserved,137); \
+ RVECENT(romReserved,138); \
+ RVECENT(romReserved,139); \
+ RVECENT(romReserved,140); \
+ RVECENT(romReserved,141); \
+ RVECENT(romReserved,142); \
+ RVECENT(romReserved,143); \
+ RVECENT(romExcHandle,0x480); /* EJTAG debug exception */
+
+#define IFX_RESET_PRECHECK \
+ mfc0 k0, CP0_EBASE; \
+ and k0, EBASEF_CPUNUM; \
+ bne k0, zero, ifx_mips_handler_1; \
+ nop;
+
+#define IFX_CPU_EXTRA_INIT \
+ mfc0 k0, CP0_CONFIG, 7; \
+ li k1, 0x04; \
+ or k0, k1; \
+ mtc0 k0, CP0_CONFIG, 7;
+
+#define IFX_CACHE_OPER_MODE \
+ li t0, CONF_CM_CACHABLE_NO_WA;
+
+/*
+ * Stop VCPU
+ */
+#define IFX_MIPS_HANDLER_1 \
+ wait; \
+ b ifx_mips_handler_1; \
+ nop;
+
diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/incaip_clock.c b/package/uboot-ifxmips/files/cpu/mips/danube/incaip_clock.c
new file mode 100644
index 000000000..1b0a0fd39
--- /dev/null
+++ b/package/uboot-ifxmips/files/cpu/mips/danube/incaip_clock.c
@@ -0,0 +1,120 @@
+/*
+ * (C) Copyright 2003
+ * 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
+ */
+
+#ifdef CONFIG_INCA_IP
+
+#include <common.h>
+#include <asm/inca-ip.h>
+
+
+/*******************************************************************************
+*
+* get_cpuclk - returns the frequency of the CPU.
+*
+* Gets the value directly from the INCA-IP hardware.
+*
+* RETURNS:
+* 150.000.000 for 150 MHz
+* 133.333.333 for 133 Mhz (= 400MHz/3)
+* 100.000.000 for 100 Mhz (= 400MHz/4)
+* NOTE:
+* This functions should be used by the hardware driver to get the correct
+* frequency of the CPU. Don't use the macros, which are set to init the CPU
+* frequency in the ROM code.
+*/
+uint incaip_get_cpuclk (void)
+{
+ /*-------------------------------------------------------------------------*/
+ /* CPU Clock Input Multiplexer (MUX I) */
+ /* Multiplexer MUX I selects the maximum input clock to the CPU. */
+ /*-------------------------------------------------------------------------*/
+ if (*((volatile ulong *) INCA_IP_CGU_CGU_MUXCR) &
+ INCA_IP_CGU_CGU_MUXCR_MUXI) {
+ /* MUX I set to 150 MHz clock */
+ return 150000000;
+ } else {
+ /* MUX I set to 100/133 MHz clock */
+ if (*((volatile ulong *) INCA_IP_CGU_CGU_DIVCR) & 0x40) {
+ /* Division value is 1/3, maximum CPU operating */
+ /* frequency is 133.3 MHz */
+ return 133333333;
+ } else {
+ /* Division value is 1/4, maximum CPU operating */
+ /* frequency is 100 MHz */
+ return 100000000;
+ }
+ }
+}
+
+/*******************************************************************************
+*
+* get_fpiclk - returns the frequency of the FPI bus.
+*
+* Gets the value directly from the INCA-IP hardware.
+*
+* RETURNS: Frquency in Hz
+*
+* NOTE:
+* This functions should be used by the hardware driver to get the correct
+* frequency of the CPU. Don't use the macros, which are set to init the CPU
+* frequency in the ROM code.
+* The calculation for the
+*/
+uint incaip_get_fpiclk (void)
+{
+ uint clkCPU;
+
+ clkCPU = incaip_get_cpuclk ();
+
+ switch (*((volatile ulong *) INCA_IP_CGU_CGU_DIVCR) & 0xC) {
+ case 0x4:
+ return clkCPU >> 1; /* devided by 2 */
+ break;
+ case 0x8:
+ return clkCPU >> 2; /* devided by 4 */
+ break;
+ default:
+ return clkCPU;
+ break;
+ }
+}
+
+int incaip_set_cpuclk (void)
+{
+ extern void ebu_init(long);
+ extern void cgu_init(long);
+ extern void sdram_init(long);
+ char tmp[64];
+ ulong cpuclk;
+
+ if (getenv_r ("cpuclk", tmp, sizeof (tmp)) > 0) {
+ cpuclk = simple_strtoul (tmp, NULL, 10) * 1000000;
+ cgu_init (cpuclk);
+ ebu_init (cpuclk);
+ sdram_init (cpuclk);
+ }
+
+ return 0;
+}
+
+#endif /* CONFIG_INCA_IP */
diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/incaip_wdt.S b/package/uboot-ifxmips/files/cpu/mips/danube/incaip_wdt.S
new file mode 100644
index 000000000..0c6b5e201
--- /dev/null
+++ b/package/uboot-ifxmips/files/cpu/mips/danube/incaip_wdt.S
@@ -0,0 +1,75 @@
+/*
+ * INCA-IP Watchdog timer management code.
+ *
+ * Copyright (c) 2003 Wolfgang Denk <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 <config.h>
+#include <version.h>
+#include <asm/regdef.h>
+
+#ifdef CONFIG_INCA_IP
+
+#define WD_BASE 0xb8000000
+#define WD_CON0(value) 0x0020(value)
+#define WD_CON1(value) 0x0024(value)
+#define WD_DISABLE 0x00000008
+#define WD_ENABLE 0x00000000
+#define WD_WRITE_PW 0xFFFC00F8
+#define WD_WRITE_ENDINIT 0xFFFC00F3
+#define WD_WRITE_INIT 0xFFFC00F2
+
+
+ .globl disable_incaip_wdt
+disable_incaip_wdt:
+ li t0, WD_BASE
+
+ /* Calculate password.
+ */
+ lw t2, WD_CON1(t0)
+ and t2, 0xC
+
+ lw t3, WD_CON0(t0)
+ and t3, 0xFFFFFF01
+
+ or t3, t2
+ or t3, 0xF0
+
+ sw t3, WD_CON0(t0) /* write password */
+
+ /* Clear ENDINIT.
+ */
+ li t1, WD_WRITE_INIT
+ sw t1, WD_CON0(t0)
+
+
+ li t1, WD_DISABLE
+ sw t1, WD_CON1(t0) /* disable watchdog */
+ li t1, WD_WRITE_PW
+ sw t1, WD_CON0(t0) /* write password */
+ li t1, WD_WRITE_ENDINIT
+ sw t1, WD_CON0(t0) /* end command */
+
+ j ra
+ nop
+
+#endif /* CONFIG_INCA_IP */
diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/interrupts.c b/package/uboot-ifxmips/files/cpu/mips/danube/interrupts.c
new file mode 100644
index 000000000..87f7a9f7e
--- /dev/null
+++ b/package/uboot-ifxmips/files/cpu/mips/danube/interrupts.c
@@ -0,0 +1,33 @@
+/*
+ * (C) Copyright 2003
+ * 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 <common.h>
+
+void enable_interrupts(void)
+{
+}
+
+int disable_interrupts(void)
+{
+ return 0;
+}
diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/start.S b/package/uboot-ifxmips/files/cpu/mips/danube/start.S
new file mode 100644
index 000000000..b1ee491d3
--- /dev/null
+++ b/package/uboot-ifxmips/files/cpu/mips/danube/start.S
@@ -0,0 +1,442 @@
+/*
+ * Startup Code for MIPS32 CPU-core
+ *
+ * Copyright (c) 2003 Wolfgang Denk <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 <config.h>
+#include <version.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#if defined(CONFIG_IFX_MIPS)
+#include "ifx_start.S"
+#endif
+
+#define RVECENT(f,n) \
+ b f; nop
+#define XVECENT(f,bev) \
+ b f ; \
+ li k0,bev
+
+ .set noreorder
+
+ .globl _start
+ .text
+_start:
+ RVECENT(reset,0) /* U-boot entry point */
+ RVECENT(reset,1) /* software reboot */
+#if defined(CONFIG_INCA_IP)
+ .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */
+ .word 0x00000000 /* phase of the flash */
+#elif defined(CONFIG_IFX_MIPS) && defined(IFX_EBU_BOOTCFG_DWORD)
+ IFX_EBU_BOOTCFG_DWORD
+#elif defined(CONFIG_PURPLE)
+ .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */
+ .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */
+#else
+ RVECENT(romReserved,2)
+#endif
+ RVECENT(romReserved,3)
+ RVECENT(romReserved,4)
+ RVECENT(romReserved,5)
+ RVECENT(romReserved,6)
+ RVECENT(romReserved,7)
+ RVECENT(romReserved,8)
+ RVECENT(romReserved,9)
+ RVECENT(romReserved,10)
+ RVECENT(romReserved,11)
+ RVECENT(romReserved,12)
+ RVECENT(romReserved,13)
+ RVECENT(romReserved,14)
+ RVECENT(romReserved,15)
+ RVECENT(romReserved,16)
+ RVECENT(romReserved,17)
+ RVECENT(romReserved,18)
+ RVECENT(romReserved,19)
+ RVECENT(romReserved,20)
+ RVECENT(romReserved,21)
+ RVECENT(romReserved,22)
+ RVECENT(romReserved,23)
+ RVECENT(romReserved,24)
+ RVECENT(romReserved,25)
+ RVECENT(romReserved,26)
+ RVECENT(romReserved,27)
+ RVECENT(romReserved,28)
+ RVECENT(romReserved,29)
+ RVECENT(romReserved,30)
+ RVECENT(romReserved,31)
+ RVECENT(romReserved,32)
+ RVECENT(romReserved,33)
+ RVECENT(romReserved,34)
+ RVECENT(romReserved,35)
+ RVECENT(romReserved,36)
+ RVECENT(romReserved,37)
+ RVECENT(romReserved,38)
+ RVECENT(romReserved,39)
+ RVECENT(romReserved,40)
+ RVECENT(romReserved,41)
+ RVECENT(romReserved,42)
+ RVECENT(romReserved,43)
+ RVECENT(romReserved,44)
+ RVECENT(romReserved,45)
+ RVECENT(romReserved,46)
+ RVECENT(romReserved,47)
+ RVECENT(romReserved,48)
+ RVECENT(romReserved,49)
+ RVECENT(romReserved,50)
+ RVECENT(romReserved,51)
+ RVECENT(romReserved,52)
+ RVECENT(romReserved,53)
+ RVECENT(romReserved,54)
+ RVECENT(romReserved,55)
+ RVECENT(romReserved,56)
+ RVECENT(romReserved,57)
+ RVECENT(romReserved,58)
+ RVECENT(romReserved,59)
+ RVECENT(romReserved,60)
+ RVECENT(romReserved,61)
+ RVECENT(romReserved,62)
+ RVECENT(romReserved,63)
+ XVECENT(romExcHandle,0x200) /* bfc00200: R4000 tlbmiss vector */
+ RVECENT(romReserved,65)
+ RVECENT(romReserved,66)
+ RVECENT(romReserved,67)
+ RVECENT(romReserved,68)
+ RVECENT(romReserved,69)
+ RVECENT(romReserved,70)
+ RVECENT(romReserved,71)
+ RVECENT(romReserved,72)
+ RVECENT(romReserved,73)
+ RVECENT(romReserved,74)
+ RVECENT(romReserved,75)
+ RVECENT(romReserved,76)
+ RVECENT(romReserved,77)
+ RVECENT(romReserved,78)
+ RVECENT(romReserved,79)
+ XVECENT(romExcHandle,0x280) /* bfc00280: R4000 xtlbmiss vector */
+ RVECENT(romReserved,81)
+ RVECENT(romReserved,82)
+ RVECENT(romReserved,83)
+ RVECENT(romReserved,84)
+ RVECENT(romReserved,85)
+ RVECENT(romReserved,86)
+ RVECENT(romReserved,87)
+ RVECENT(romReserved,88)
+ RVECENT(romReserved,89)
+ RVECENT(romReserved,90)
+ RVECENT(romReserved,91)
+ RVECENT(romReserved,92)
+ RVECENT(romReserved,93)
+ RVECENT(romReserved,94)
+ RVECENT(romReserved,95)
+ XVECENT(romExcHandle,0x300) /* bfc00300: R4000 cache vector */
+ RVECENT(romReserved,97)
+ RVECENT(romReserved,98)
+ RVECENT(romReserved,99)
+ RVECENT(romReserved,100)
+ RVECENT(romReserved,101)
+ RVECENT(romReserved,102)
+ RVECENT(romReserved,103)
+ RVECENT(romReserved,104)
+ RVECENT(romReserved,105)
+ RVECENT(romReserved,106)
+ RVECENT(romReserved,107)
+ RVECENT(romReserved,108)
+ RVECENT(romReserved,109)
+ RVECENT(romReserved,110)
+ RVECENT(romReserved,111)
+ XVECENT(romExcHandle,0x380) /* bfc00380: R4000 general vector */
+ RVECENT(romReserved,113)
+ RVECENT(romReserved,114)
+ RVECENT(romReserved,115)
+ RVECENT(romReserved,116)
+ RVECENT(romReserved,116)
+ RVECENT(romReserved,118)
+ RVECENT(romReserved,119)
+ RVECENT(romReserved,120)
+ RVECENT(romReserved,121)
+ RVECENT(romReserved,122)
+ RVECENT(romReserved,123)
+ RVECENT(romReserved,124)
+ RVECENT(romReserved,125)
+ RVECENT(romReserved,126)
+ RVECENT(romReserved,127)
+
+ /* We hope there are no more reserved vectors!
+ * 128 * 8 == 1024 == 0x400
+ * so this is address R_VEC+0x400 == 0xbfc00400
+ */
+#if defined(CONFIG_IFX_MIPS) && defined(IFX_MORE_RESERVED_VECTORS)
+ IFX_MORE_RESERVED_VECTORS
+#else
+#ifdef CONFIG_PURPLE
+/* 0xbfc00400 */
+ .word 0xdc870000
+ .word 0xfca70000
+ .word 0x20840008
+ .word 0x20a50008
+ .word 0x20c6ffff
+ .word 0x14c0fffa
+ .word 0x00000000
+ .word 0x03e00008
+ .word 0x00000000
+ .word 0x00000000
+/* 0xbfc00428 */
+ .word 0xdc870000
+ .word 0xfca70000
+ .word 0x20840008
+ .word 0x20a50008
+ .word 0x20c6ffff
+ .word 0x14c0fffa
+ .word 0x00000000
+ .word 0x03e00008
+ .word 0x00000000
+ .word 0x00000000
+#endif /* CONFIG_PURPLE */
+#endif /* CONFIG_IFX_MIPS */
+ .align 4
+reset:
+#if defined(CONFIG_IFX_MIPS) && defined(IFX_RESET_PRECHECK)
+ IFX_RESET_PRECHECK
+#endif
+ /* Clear watch registers.
+ */
+ mtc0 zero, CP0_WATCHLO
+ mtc0 zero, CP0_WATCHHI
+
+ /* STATUS register */
+#ifdef CONFIG_TB0229
+ li k0, ST0_CU0
+#else
+ mfc0 k0, CP0_STATUS
+#endif
+ li k1, ~ST0_IE
+ and k0, k1
+ mtc0 k0, CP0_STATUS
+
+ /* CAUSE register */
+ mtc0 zero, CP0_CAUSE
+
+#if defined(CONFIG_IFX_MIPS) && defined(IFX_CPU_EXTRA_INIT)
+ IFX_CPU_EXTRA_INIT
+#endif
+
+ /* Init Timer */
+ mtc0 zero, CP0_COUNT
+ mtc0 zero, CP0_COMPARE
+
+ /* CONFIG0 register */
+ li t0, CONF_CM_UNCACHED
+ mtc0 t0, CP0_CONFIG
+
+ /* Initialize GOT pointer.
+ */
+ bal 1f
+ nop
+ .word _GLOBAL_OFFSET_TABLE_
+ 1:
+ move gp, ra
+ lw t1, 0(ra)
+ move gp, t1
+
+#ifdef CONFIG_INCA_IP
+ /* Disable INCA-IP Watchdog.
+ */
+ la t9, disable_incaip_wdt
+ jalr t9
+ nop
+#endif
+
+ /* Initialize any external memory.
+ */
+ la t9, lowlevel_init
+ jalr t9
+ nop
+
+ /* Initialize caches...
+ */
+ la t9, mips_cache_reset
+ jalr t9
+ nop
+
+ /* ... and enable them.
+ */
+#if defined(CONFIG_IFX_MIPS) && defined(IFX_CACHE_OPER_MODE)
+ IFX_CACHE_OPER_MODE
+#else
+ li t0, CONF_CM_CACHABLE_NONCOHERENT
+#endif
+ mtc0 t0, CP0_CONFIG
+
+
+ /* Set up temporary stack.
+ */
+ li a0, CFG_INIT_SP_OFFSET
+ la t9, mips_cache_lock
+ jalr t9
+ nop
+
+ li t0, CFG_SDRAM_BASE + CFG_INIT_SP_OFFSET
+ la sp, 0(t0)
+
+ la t9, board_init_f
+ j t9
+ nop
+
+#ifdef CFG_HEAD_CODE
+/*
+ * void jump_unconditional (addr)
+ * This function simply jumps to the location pointed by a0.
+ * a0 = target_location
+ *
+ */
+ .globl jump_unconditional
+ .ent jump_unconditional
+jump_unconditional:
+ move t9, a0
+ j t9
+ nop
+ .end jump_unconditional
+
+#endif
+
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * a0 = addr_sp
+ * a1 = gd
+ * a2 = destination address
+ */
+ .globl relocate_code
+ .ent relocate_code
+relocate_code:
+ move sp, a0 /* Set new stack pointer */
+
+#ifdef CFG_HEAD_CODE
+ li t0, CFG_HEAD_BASE
+#else
+ li t0, CFG_MONITOR_BASE
+#endif
+ la t3, in_ram
+ lw t2, -12(t3) /* t2 <-- uboot_end_data */
+ move t1, a2
+
+ /*
+ * Fix GOT pointer:
+ *
+ * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
+ */
+ move t6, gp
+#ifdef CFG_HEAD_CODE
+ sub gp, CFG_HEAD_BASE
+#else
+ sub gp, CFG_MONITOR_BASE
+#endif
+ add gp, a2 /* gp now adjusted */
+ sub t6, gp, t6 /* t6 <-- relocation offset */
+
+ /*
+ * t0 = source address
+ * t1 = target address
+ * t2 = source end address
+ */
+ /* On the purple board we copy the code earlier in a special way
+ * in order to solve flash problems
+ */
+#ifndef CONFIG_PURPLE
+1:
+ lw t3, 0(t0)
+ sw t3, 0(t1)
+ addu t0, 4
+ ble t0, t2, 1b
+ addu t1, 4 /* delay slot */
+#endif
+
+ /* If caches were enabled, we would have to flush them here.
+ */
+
+ /* Jump to where we've relocated ourselves.
+ */
+ addi t0, a2, in_ram - _start
+ j t0
+ nop
+
+ .word uboot_end_data
+ .word uboot_end
+ .word num_got_entries
+
+in_ram:
+ /* Now we want to update GOT.
+ */
+ lw t3, -4(t0) /* t3 <-- num_got_entries */
+ addi t4, gp, 8 /* Skipping first two entries. */
+ li t2, 2
+1:
+ lw t1, 0(t4)
+ beqz t1, 2f
+ add t1, t6
+ sw t1, 0(t4)
+2:
+ addi t2, 1
+ blt t2, t3, 1b
+ addi t4, 4 /* delay slot */
+
+ /* Clear BSS.
+ */
+ lw t1, -12(t0) /* t1 <-- uboot_end_data */
+ lw t2, -8(t0) /* t2 <-- uboot_end */
+ add t1, t6 /* adjust pointers */
+ add t2, t6
+
+ sub t1, 4
+1: addi t1, 4
+ bltl t1, t2, 1b
+ sw zero, 0(t1) /* delay slot */
+
+ move a0, a1
+ la t9, board_init_r
+ j t9
+ move a1, a2 /* delay slot */
+
+ .end relocate_code
+
+
+ /* Exception handlers.
+ */
+romReserved:
+ b romReserved
+
+romExcHandle:
+ b romExcHandle
+
+ /* Additional handlers.
+ */
+#if defined(CONFIG_IFX_MIPS)
+#if defined(IFX_MIPS_HANDLER_1)
+ifx_mips_handler_1:
+ IFX_MIPS_HANDLER_1
+#endif
+#endif
+
diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/start_bootstrap.S b/package/uboot-ifxmips/files/cpu/mips/danube/start_bootstrap.S
new file mode 100644
index 000000000..cd7a13fab
--- /dev/null
+++ b/package/uboot-ifxmips/files/cpu/mips/danube/start_bootstrap.S
@@ -0,0 +1,428 @@
+/*
+ * Startup Code for MIPS32 CPU-core
+ *
+ * Copyright (c) 2003 Wolfgang Denk <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 <config.h>
+#include <version.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+
+
+#define RVECENT(f,n) \
+ b f; nop
+#define XVECENT(f,bev) \
+ b f ; \
+ li k0,bev
+
+ .set noreorder
+
+ .globl _start_bootstrap
+ .text
+_start_bootstrap:
+ RVECENT(reset,0) /* U-boot entry point */
+ RVECENT(reset,1) /* software reboot */
+#if defined(CONFIG_INCA_IP) || defined(CONFIG_INCA_IP2)
+ .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */
+ .word 0x00000000 /* phase of the flash */
+#elif defined(CONFIG_PURPLE)
+ .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */
+ .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */
+#elif defined(CONFIG_DANUBE)
+
+ .org 0x10
+ .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */
+ .word 0x00000000 /* phase of the flash */
+
+ .org 0x18
+ .word 0x312E3000 /* version x.x */
+ .word 0x00000000 /* phase of the flash */
+#else
+ RVECENT(romReserved,2)
+#endif
+ RVECENT(romReserved,3)
+ RVECENT(romReserved,4)
+ RVECENT(romReserved,5)
+ RVECENT(romReserved,6)
+ RVECENT(romReserved,7)
+ RVECENT(romReserved,8)
+ RVECENT(romReserved,9)
+ RVECENT(romReserved,10)
+ RVECENT(romReserved,11)
+ RVECENT(romReserved,12)
+ RVECENT(romReserved,13)
+ RVECENT(romReserved,14)
+ RVECENT(romReserved,15)
+ RVECENT(romReserved,16)
+ RVECENT(romReserved,17)
+ RVECENT(romReserved,18)
+ RVECENT(romReserved,19)
+ RVECENT(romReserved,20)
+ RVECENT(romReserved,21)
+ RVECENT(romReserved,22)
+ RVECENT(romReserved,23)
+ RVECENT(romReserved,24)
+ RVECENT(romReserved,25)
+ RVECENT(romReserved,26)
+ RVECENT(romReserved,27)
+ RVECENT(romReserved,28)
+ RVECENT(romReserved,29)
+ RVECENT(romReserved,30)
+ RVECENT(romReserved,31)
+ RVECENT(romReserved,32)
+ RVECENT(romReserved,33)
+ RVECENT(romReserved,34)
+ RVECENT(romReserved,35)
+ RVECENT(romReserved,36)
+ RVECENT(romReserved,37)
+ RVECENT(romReserved,38)
+ RVECENT(romReserved,39)
+ RVECENT(romReserved,40)
+ RVECENT(romReserved,41)
+ RVECENT(romReserved,42)
+ RVECENT(romReserved,43)
+ RVECENT(romReserved,44)
+ RVECENT(romReserved,45)
+ RVECENT(romReserved,46)
+ RVECENT(romReserved,47)
+ RVECENT(romReserved,48)
+ RVECENT(romReserved,49)
+ RVECENT(romReserved,50)
+ RVECENT(romReserved,51)
+ RVECENT(romReserved,52)
+ RVECENT(romReserved,53)
+ RVECENT(romReserved,54)
+ RVECENT(romReserved,55)
+ RVECENT(romReserved,56)
+ RVECENT(romReserved,57)
+ RVECENT(romReserved,58)
+ RVECENT(romReserved,59)
+ RVECENT(romReserved,60)
+ RVECENT(romReserved,61)
+ RVECENT(romReserved,62)
+ RVECENT(romReserved,63)
+ XVECENT(romExcHandle,0x200) /* bfc00200: R4000 tlbmiss vector */
+ RVECENT(romReserved,65)
+ RVECENT(romReserved,66)
+ RVECENT(romReserved,67)
+ RVECENT(romReserved,68)
+ RVECENT(romReserved,69)
+ RVECENT(romReserved,70)
+ RVECENT(romReserved,71)
+ RVECENT(romReserved,72)
+ RVECENT(romReserved,73)
+ RVECENT(romReserved,74)
+ RVECENT(romReserved,75)
+ RVECENT(romReserved,76)
+ RVECENT(romReserved,77)
+ RVECENT(romReserved,78)
+ RVECENT(romReserved,79)
+ XVECENT(romExcHandle,0x280) /* bfc00280: R4000 xtlbmiss vector */
+ RVECENT(romReserved,81)
+ RVECENT(romReserved,82)
+ RVECENT(romReserved,83)
+ RVECENT(romReserved,84)
+ RVECENT(romReserved,85)
+ RVECENT(romReserved,86)
+ RVECENT(romReserved,87)
+ RVECENT(romReserved,88)
+ RVECENT(romReserved,89)
+ RVECENT(romReserved,90)
+ RVECENT(romReserved,91)
+ RVECENT(romReserved,92)
+ RVECENT(romReserved,93)
+ RVECENT(romReserved,94)
+ RVECENT(romReserved,95)
+ XVECENT(romExcHandle,0x300) /* bfc00300: R4000 cache vector */
+ RVECENT(romReserved,97)
+ RVECENT(romReserved,98)
+ RVECENT(romReserved,99)
+ RVECENT(romReserved,100)
+ RVECENT(romReserved,101)
+ RVECENT(romReserved,102)
+ RVECENT(romReserved,103)
+ RVECENT(romReserved,104)
+ RVECENT(romReserved,105)
+ RVECENT(romReserved,106)
+ RVECENT(romReserved,107)
+ RVECENT(romReserved,108)
+ RVECENT(romReserved,109)
+ RVECENT(romReserved,110)
+ RVECENT(romReserved,111)
+ XVECENT(romExcHandle,0x380) /* bfc00380: R4000 general vector */
+ RVECENT(romReserved,113)
+ RVECENT(romReserved,114)
+ RVECENT(romReserved,115)
+ RVECENT(romReserved,116)
+ RVECENT(romReserved,116)
+ RVECENT(romReserved,118)
+ RVECENT(romReserved,119)
+ RVECENT(romReserved,120)
+ RVECENT(romReserved,121)
+ RVECENT(romReserved,122)
+ RVECENT(romReserved,123)
+ RVECENT(romReserved,124)
+ RVECENT(romReserved,125)
+ RVECENT(romReserved,126)
+ RVECENT(romReserved,127)
+
+ /* We hope there are no more reserved vectors!
+ * 128 * 8 == 1024 == 0x400
+ * so this is address R_VEC+0x400 == 0xbfc00400
+ */
+#ifdef CONFIG_PURPLE
+/* 0xbfc00400 */
+ .word 0xdc870000
+ .word 0xfca70000
+ .word 0x20840008
+ .word 0x20a50008
+ .word 0x20c6ffff
+ .word 0x14c0fffa
+ .word 0x00000000
+ .word 0x03e00008
+ .word 0x00000000
+ .word 0x00000000
+/* 0xbfc00428 */
+ .word 0xdc870000
+ .word 0xfca70000
+ .word 0x20840008
+ .word 0x20a50008
+ .word 0x20c6ffff
+ .word 0x14c0fffa
+ .word 0x00000000
+ .word 0x03e00008
+ .word 0x00000000
+ .word 0x00000000
+#endif /* CONFIG_PURPLE */
+ .align 4
+reset:
+#ifdef CONFIG_INCA_IP2
+ /* Check for Host or Voice CPU */
+
+ mfc0 k0, CP0_EBASE
+ and k0, EBASEF_CPUNUM
+ srl k0, EBASEB_CPUNUM
+ subu k0, EBASE_CPU_HOST
+ bne k0, zero, voice_reset_handler
+ nop
+
+#endif
+
+ /* Clear watch registers.
+ */
+ mtc0 zero, CP0_WATCHLO
+ mtc0 zero, CP0_WATCHHI
+
+ /* STATUS register */
+#ifdef CONFIG_TB0229
+ li k0, ST0_CU0
+#else
+ mfc0 k0, CP0_STATUS
+#endif
+ li k1, ~ST0_IE
+ and k0, k1
+ mtc0 k0, CP0_STATUS
+
+ /* CAUSE register */
+ mtc0 zero, CP0_CAUSE
+
+#ifdef CONFIG_INCA_IP2
+ /* CONFIG7 register */
+ mfc0 k0, CP0_CONFIG, 7
+ li k1, 4 /* Disable RPS due to E83 bug of 24KEC */
+ or k0, k1
+ mtc0 k0, CP0_CONFIG, 7
+#endif
+ /* Init Timer */
+ mtc0 zero, CP0_COUNT
+ mtc0 zero, CP0_COMPARE
+
+ /* CONFIG0 register */
+ li t0, CONF_CM_UNCACHED
+ mtc0 t0, CP0_CONFIG
+
+ /* Initialize GOT pointer.
+ */
+ bal 1f
+ nop
+ .word _GLOBAL_OFFSET_TABLE_
+ 1:
+ move gp, ra
+ lw t1, 0(ra)
+ move gp, t1
+
+#ifdef CONFIG_INCA_IP
+ /* Disable INCA-IP Watchdog.
+ */
+ la t9, disable_incaip_wdt
+ jalr t9
+ nop
+#endif
+
+ /* Initialize any external memory.
+ */
+ la t9, lowlevel_init
+ jalr t9
+ nop
+
+ /* Initialize caches...
+ */
+ la t9, mips_cache_reset
+ jalr t9
+ nop
+
+ /* ... and enable them.
+ */
+#ifdef CONFIG_MIPS_FORCE_CACHE_WRITE_THROUGH
+ li t0, CONF_CM_CACHABLE_NO_WA
+#else
+ li t0, CONF_CM_CACHABLE_NONCOHERENT
+#endif
+ mtc0 t0, CP0_CONFIG
+
+
+ /* Set up temporary stack.
+ */
+ li a0, CFG_INIT_SP_OFFSET
+ la t9, mips_cache_lock
+ jalr t9
+ nop
+
+ li t0, CFG_SDRAM_BASE + CFG_INIT_SP_OFFSET
+ la sp, 0(t0)
+
+ la t9, bootstrap_board_init_f
+ j t9
+ nop
+
+
+/*
+ * void bootstrap_relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * a0 = addr_sp
+ * a1 = gd
+ * a2 = destination address
+ */
+ .globl bootstrap_relocate_code
+ .ent bootstrap_relocate_code
+bootstrap_relocate_code:
+ move sp, a0 /* Set new stack pointer */
+
+ li t0, BOOTSTRAP_CFG_MONITOR_BASE
+ la t3, in_ram
+ lw t2, -12(t3) /* t2 <-- uboot_end_data_bootsrap */
+ move t1, a2
+
+ /*
+ * Fix GOT pointer:
+ *
+ * New GOT-PTR = (old GOT-PTR - BOOTSTRAP_CFG_MONITOR_BASE) + Destination Address
+ */
+ move t6, gp
+ sub gp, BOOTSTRAP_CFG_MONITOR_BASE
+ add gp, a2 /* gp now adjusted */
+ sub t6, gp, t6 /* t6 <-- relocation offset */
+
+ /*
+ * t0 = source address
+ * t1 = target address
+ * t2 = source end address
+ */
+ /* On the purple board we copy the code earlier in a special way
+ * in order to solve flash problems
+ */
+#ifndef CONFIG_PURPLE
+1:
+ lw t3, 0(t0)
+ sw t3, 0(t1)
+ addu t0, 4
+ ble t0, t2, 1b
+ addu t1, 4 /* delay slot */
+#endif
+
+ /* If caches were enabled, we would have to flush them here.
+ */
+
+ /* Jump to where we've relocated ourselves.
+ */
+ addi t0, a2, in_ram - _start_bootstrap
+ j t0
+ nop
+
+ .word uboot_end_data_bootstrap
+ .word uboot_end_bootstrap
+ .word num_got_entries
+
+in_ram:
+ /* Now we want to update GOT.
+ */
+ lw t3, -4(t0) /* t3 <-- num_got_entries */
+ addi t4, gp, 8 /* Skipping first two entries. */
+ li t2, 2
+1:
+ lw t1, 0(t4)
+ beqz t1, 2f
+ add t1, t6
+ sw t1, 0(t4)
+2:
+ addi t2, 1
+ blt t2, t3, 1b
+ addi t4, 4 /* delay slot */
+
+ /* Clear BSS.
+ */
+ lw t1, -12(t0) /* t1 <-- uboot_end_data_bootstrap */
+ lw t2, -8(t0) /* t2 <-- uboot_end_bootstrap */
+ add t1, t6 /* adjust pointers */
+ add t2, t6
+
+ sub t1, 4
+1: addi t1, 4
+ bltl t1, t2, 1b
+ sw zero, 0(t1) /* delay slot */
+
+ move a0, a1
+ la t9, bootstrap_board_init_r
+ j t9
+ move a1, a2 /* delay slot */
+
+ .end bootstrap_relocate_code
+
+
+ /* Exception handlers.
+ */
+romReserved:
+ b romReserved
+
+romExcHandle:
+ b romExcHandle
+
+#ifdef CONFIG_INCA_IP2
+voice_reset_handler:
+ wait
+ b voice_reset_handler
+ nop
+#endif